Codex Desktop (Windows): code-mode host exits during handshake, breaking every tool call for code_mode_only models
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
Summary
On Codex Desktop for Windows, every tool call fails with:
dispatch_tool_call_with_terminal_outcome: error=code-mode host exited during handshake
Because gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna and gpt-reserve are tool_mode = code_mode_only, this makes the whole 5.6 model family unusable in the desktop app — the agent cannot run a single command, read a file, or use any skill/plugin.
The same codex.exe binary works correctly when run as a CLI. The failure is specific to the desktop app's app-server, and it reproduces with a completely empty CODEX_HOME, so it is not caused by user configuration.
Environment
| OS | Windows 11 26100/26200 (10.0.26200), x64, zh-CN locale |
| Codex Desktop | package 26.825.4187.0, internal version 26.825.32147 |
| codex-cli | 0.150.0-alpha.12.2 |
| Auth | ChatGPT (Plus) |
| Models affected | gpt-5.6-terra, gpt-5.6-luna (tool_mode = code_mode_only) |
| Models unaffected | gpt-5.5, gpt-5.4 (tool_mode = None) |
Reproduction
- Open Codex Desktop, select
gpt-5.6-terra. - Ask it to run any command, e.g.
execute echo hello. - The tool call fails;
logs_2.sqliterecordscode-mode host exited during handshake.
Observed 100% of the time, across dozens of attempts over three days.
Key evidence: reproduces with an empty CODEX_HOME
Set CODEX_HOME to a fresh directory containing only auth.json, restart the desktop app, and retry. Same failure. From that clean home's logs_2.sqlite:
16:48:38 (CLI) exec_command failed ... CreateProcess { message: "Rejected(...)" }
17:22:22 (Desktop) dispatch_tool_call_with_terminal_outcome: error=code-mode host exited during handshake
No config, no MCP servers, no plugins, no history — the desktop app still fails, while the CLI against the same home gets past the handshake and executes the command.
Also ruled out by direct testing: disabling all 4 MCP servers, disabling all 13 plugins, resetting cap_sid, and clearing accumulated sandbox ACEs. None changed the desktop behaviour.
What the host process actually does
Captured via WMI process polling (40 ms) while reproducing:
START pid=11856 ppid=20120(codex) codex-code-mode-host.exe
"C:\Users\<user>\AppData\Local\OpenAI\Codex\bin\<hash>\codex-code-mode-host.exe"
EXIT pid=11856 (~190 ms later)
The process is spawned (so this is not AV blocking process creation) with no arguments, and dies shortly after.
Driving codex-code-mode-host.exe --listen stdio manually shows exactly two ways it can exit that early:
| stdin condition | result |
|---|---|
| pipe, no data written | stays alive indefinitely |
| stdin closed immediately (EOF) | exit 0 after ~20 ms |
| non-code-mode bytes (e.g. a JSON-RPC frame) | exit 1 after ~20 ms, Error: failed to read code-mode client hello |
So the host is healthy; it is the app-server that fails to deliver a valid client hello over the stdio transport.
For reference, the IPC framing is a little-endian u32 length prefix followed by JSON requiring a type field, with a 64 MiB frame cap. Feeding it a JSON-RPC message produces:
Error: failed to read code-mode client hello
Caused by:
code-mode IPC frame length 1936335483 exceeds 67108864 bytes
(1936335483 = 0x736A227B = the first four bytes of {"jsonrpc" read as LE u32.) That is consistent with the host receiving something other than a code-mode hello on stdin — possibly the app-server's own JSON-RPC channel — but I could not confirm the actual bytes the app-server writes.
The host binary itself is fine: SHA-256 matches the copy shipped in the MSIX package, Authenticode signature is valid (OpenAI OpCo, LLC), and it starts correctly standalone in stdio mode, in grpc:// mode, and when launched inside codex sandbox.
Things that are NOT the cause (verified)
- Endpoint protection (ESET Internet Security 19.2.7.0) — no detections, and the host process is created successfully
- Corrupted or tampered binaries — hashes and signatures verified
node_replMCP server / bundled Node kernel — MCP handshake andjstool calls work- Bundled Python runtime (3.12.13) and Node (v24.19.0) — both execute fine
- Missing document/pdf/spreadsheet plugins — present on disk
- Model API connectivity —
codex doctorreports WebSocket 101 and auth OK - Any user configuration — reproduces with an empty
CODEX_HOME
Secondary bug: Windows sandbox cannot create a token (error 1344)
Separate from the above, and visible on the CLI path:
exec_command failed for `pwsh.exe -Command 'echo hello'`:
CreateProcess { message: "Rejected(\"Failed to create unified exec process:
SetTokenInformation(TokenDefaultDacl) failed: 1344\")" }
1344 is ERROR_NO_MORE_MEMORY_FOR_SECURITY_INFO — the security descriptor being applied is too large.
This appears to be driven by two unbounded caches:
-
$CODEX_HOME/cap_sidgrows one capability SID per writable root path, forever. On this machine it had reached 143 SIDs / 12,485 bytes, because a session had once used the user's home directory as its workspace — Codex minted a separate SID for each of the 141 entries under it. -
The matching capability deny ACEs written onto world-writable directories are never removed.
C:\Users\Publichad accumulated 288 ACEs (10,264-byte security descriptor) andC:\QLDownload285, versus ~4 on a normal directory. 139 orphaned SIDs on each — one per sandbox session.
The CLI degrades gracefully here (with approval_policy = OnRequest it falls back to asking the user to approve running outside the sandbox), so it stays usable. The desktop app runs with approval_policy = Never and sandbox_policy = DangerFullAccess, so there is no fallback path.
Note that clearing both caches did not fix the handshake failure — they are independent issues.
Impact
The 5.6 model family is entirely unusable in Codex Desktop on this machine. Current workarounds:
- Use the CLI for 5.6 models (approve each command when the sandbox fails)
- Use
gpt-5.5/gpt-5.4in the desktop app (tool_mode = None, so they bypass code mode)
A smaller, separate observation
When the code-mode tool call fails, the model frequently presents the expected output as if the command had run — e.g. answering with a hello code block after custom_tool_call_output was code-mode host exited during handshake. From the rollout JSONL:
{"type":"custom_tool_call_output","output":"code-mode host exited during handshake"}
{"type":"message","role":"assistant","content":[{"type":"output_text","text":"`hello`"}],"phase":"final_answer"}
This made the failure look intermittent for a long time and cost real debugging effort. It might be worth surfacing tool-call failures more explicitly to the model, or to the user in the transcript.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the Desktop app-server's stdio launch path for codex-code-mode-host.exe and compare it with the working CLI path. Use logs_2.sqlite, an empty CODEX_HOME, and the documented standalone host behavior to identify what reaches the handshake. Done means affected code-mode-only models complete a tool call in Desktop; treat the Windows token/ACE accumulation and transcript behavior as separate findings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, desktop-dev, operating-systems
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 38/100