exec_command never returns and yield_time_ms never fires: tool call orphaned with no output record
What version of Codex CLI is running?
0.144.6 at the time of the incident. The machine is now on 0.146.0, which is what the doctor report reflects. The relevant code path is unchanged in 0.146.0 (see Source observation).
What subscription do you have?
API key auth (stored auth mode: api_key), not a ChatGPT plan.
Which model were you using?
gpt-5.6-sol, reasoning effort high.
What platform is your computer?
Darwin 25.5.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
Not recorded. The process is gone.
This ran through a third-party app-server bridge that owns the control path, not stock codex in a terminal. Relevant to reproducing it.
Codex doctor report
Home paths, session UUIDs, unrelated rollout filenames, a project name, and usage counts are redacted.
<details>
<summary>codex doctor --json</summary>
{
"schemaVersion": 1,
"generatedAt": "1785798394s since unix epoch",
"overallStatus": "warning",
"codexVersion": "0.146.0",
"checks": {
"app_server.status": {
"id": "app_server.status",
"category": "app-server",
"status": "ok",
"summary": "background server is not running",
"details": {
"control socket": "/Users/<redacted>/.codex/app-server-control/app-server-control.sock",
"daemon state dir": "/Users/<redacted>/.codex/app-server-daemon",
"mode": "ephemeral",
"pid file": "/Users/<redacted>/.codex/app-server-daemon/app-server.pid (missing)",
"settings": "/Users/<redacted>/.codex/app-server-daemon/settings.json (missing)",
"status": "not running",
"update-loop pid file": "/Users/<redacted>/.codex/app-server-daemon/app-server-updater.pid (missing)"
},
"remediation": null,
"durationMs": 0
},
"auth.credentials": {
"id": "auth.credentials",
"category": "auth",
"status": "ok",
"summary": "auth is configured",
"details": {
"auth file": "/Users/<redacted>/.codex/auth.json",
"auth storage mode": "File",
"stored API key": "true",
"stored ChatGPT tokens": "false",
"stored agent identity": "false",
"stored auth mode": "api_key"
},
"remediation": null,
"durationMs": 0
},
"config.load": {
"id": "config.load",
"category": "config",
"status": "ok",
"summary": "config loaded",
"details": {
"CODEX_HOME": "/Users/<redacted>/.codex",
"config.toml": "/Users/<redacted>/.codex/config.toml",
"config.toml parse": "ok",
"cwd": "/private/tmp",
"enabled feature flags": "shell_tool, unified_exec, shell_snapshot, code_mode_host, terminal_resize_reflow, sqlite, hooks, enable_request_compression, multi_agent, apps, tool_search_always_defer_mcp_tools, tool_suggest, plugins, in_app_browser, in_app_updates, browser_use, browser_use_full_cdp_access, browser_use_external, computer_use, remote_plugin, plugin_sharing, image_generation, resize_all_images, item_ids, skill_mcp_dependency_install, skill_search, mentions_v2, steer, guardian_approval, goals, collaboration_modes, tool_call_mcp_elicitation, auth_elicitation, personality, fast_mode, tui_app_server, remote_compaction_v2, workspace_dependencies",
"feature flag overrides": "none",
"feature flags enabled": "38",
"log dir": "/Users/<redacted>/.codex/log",
"mcp servers": "6",
"model": "gpt-5.6-sol",
"model provider": "openai",
"sqlite home": "/Users/<redacted>/.codex"
},
"remediation": null,
"durationMs": 0
},
"git.environment": {
"id": "git.environment",
"category": "git",
"status": "ok",
"summary": "git version 2.50.1 (Apple Git-155)",
"details": {
"PATH git #1": "/usr/bin/git",
"PATH git entries": "1",
"git build options": "git version 2.50.1 (Apple Git-155); cpu: arm64; no commit associated with this build; sizeof-long: 8; sizeof-size_t: 8; shell-path: /bin/sh; feature: fsmonitor--daemon; libcurl: 8.7.1; zlib: 1.2.12; SHA-1: SHA1_DC; SHA-256: SHA256_BLK",
"git exec path": "/Applications/Xcode.app/Contents/Developer/usr/libexec/git-core",
"git version": "git version 2.50.1 (Apple Git-155)",
"repo detected": "false",
"selected git": "/usr/bin/git"
},
"remediation": null,
"durationMs": 293
},
"installation": {
"id": "installation",
"category": "install",
"status": "ok",
"summary": "installation looks consistent",
"details": {
"PATH codex #1": "/opt/homebrew/bin/codex",
"PATH codex #2": "/opt/homebrew/bin/codex",
"PATH codex entries": "2",
"current executable": "/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/bin/codex",
"install context": "npm (package /opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin, bin /opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/bin, resources /opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-resources, path /opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path)",
"managed by bun": "false",
"managed by npm": "true",
"managed by pnpm": "false",
"managed package root": "/opt/homebrew/lib/node_modules/@openai/codex",
"npm update target": "/opt/homebrew/lib/node_modules/@openai/codex"
},
"remediation": null,
"durationMs": 164
},
"mcp.config": {
"id": "mcp.config",
"category": "mcp",
"status": "ok",
"summary": "MCP configuration is locally consistent",
"details": {
"configured servers": "6",
"disabled servers": "0",
"stdio servers": "6"
},
"remediation": null,
"durationMs": 0
},
"network.env": {
"id": "network.env",
"category": "network",
"status": "ok",
"summary": "network-related environment looks readable",
"details": {
"CODEX_CA_CERTIFICATE": "readable file /Users/<redacted>/.local/state/<project-redacted>/ca/<redacted>-ca.pem",
"proxy env vars": "none"
},
"remediation": null,
"durationMs": 0
},
"network.provider_reachability": {
"id": "network.provider_reachability",
"category": "reachability",
"status": "ok",
"summary": "active provider endpoints are reachable over HTTP",
"details": {
"openai API base URL": "https://api.openai.com/v1 reachable (HTTP 404)",
"openai API route probe": "https://api.openai.com/v1/<redacted> route exists (HTTP 401)",
"reachability mode": "API key auth"
},
"remediation": null,
"durationMs": 831
},
"network.websocket_reachability": {
"id": "network.websocket_reachability",
"category": "websocket",
"status": "ok",
"summary": "Responses WebSocket handshake succeeded",
"details": {
"DNS": "2 IPv4, 0 IPv6, first IPv4",
"auth mode": "api_key",
"connect timeout": "15000 ms",
"endpoint": "wss://api.openai.com/v1/<redacted>",
"handshake result": "HTTP 101 Switching Protocols",
"model provider": "openai",
"models etag present": "false",
"provider name": "OpenAI",
"proxy env vars": "none",
"reasoning header": "false",
"server model present": "false",
"supports websockets": "true",
"wire API": "responses"
},
"remediation": null,
"durationMs": 915
},
"runtime.provenance": {
"id": "runtime.provenance",
"category": "runtime",
"status": "ok",
"summary": "running npm on macos-aarch64",
"details": {
"commit": "unknown",
"current executable": "/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/bin/codex",
"install method": "npm (package /opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin, bin /opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/bin, resources /opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-resources, path /opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path)",
"platform": "macos-aarch64",
"version": "0.146.0"
},
"remediation": null,
"durationMs": 0
},
"runtime.search": {
"id": "runtime.search",
"category": "search",
"status": "ok",
"summary": "search is OK (bundled)",
"details": {
"search command": "/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex-path/rg",
"search command readiness": "file exists",
"search provider": "bundled"
},
"remediation": null,
"durationMs": 0
},
"sandbox.helpers": {
"id": "sandbox.helpers",
"category": "sandbox",
"status": "ok",
"summary": "sandbox configuration is readable",
"details": {
"approval policy": "OnRequest",
"codex-linux-sandbox helper": "none",
"execve wrapper helper": "/Users/<redacted>/.codex/tmp/arg0/codex-arg0urFm68/codex-execve-wrapper",
"filesystem sandbox": "restricted",
"network sandbox": "restricted"
},
"remediation": null,
"durationMs": 0
},
"state.paths": {
"id": "state.paths",
"category": "state",
"status": "ok",
"summary": "state paths and databases are inspectable",
"details": {
"CODEX_HOME": "/Users/<redacted>/.codex (dir)",
"active rollout files": "4423 files, 18606564290 total bytes, 4206774 average bytes",
"archived rollout files": "0 files, 0 total bytes, 0 average bytes",
"goals DB": "/Users/<redacted>/.codex/goals_1.sqlite (file)",
"goals DB integrity": "ok",
"log DB": "/Users/<redacted>/.codex/logs_2.sqlite (file)",
"log DB integrity": "ok",
"log dir": "/Users/<redacted>/.codex/log (dir)",
"memories DB": "/Users/<redacted>/.codex/memories_1.sqlite (file)",
"memories DB integrity": "ok",
"sqlite home": "/Users/<redacted>/.codex (dir)",
"state DB": "/Users/<redacted>/.codex/state_5.sqlite (file)",
"state DB integrity": "ok",
"thread history DB": "/Users/<redacted>/.codex/thread_history_1.sqlite (missing)",
"thread history DB integrity": "skipped (missing)"
},
"remediation": null,
"durationMs": 832
},
"state.rollout_db_parity": {
"id": "state.rollout_db_parity",
"category": "threads",
"status": "warning",
"summary": "rollout files and state DB thread inventory differ",
"details": {
"default model provider": "openai",
"rollout DB active files": "4254",
"rollout DB active rows": "4274",
"rollout DB archive mismatches": "0",
"rollout DB archived files": "0",
"rollout DB archived rows": "0",
"rollout DB duplicate DB paths": "0",
"rollout DB duplicate rollout thread ids": "0",
"rollout DB malformed file names": "0",
"rollout DB missing active rows": "2",
"rollout DB missing active sample": [
"/Users/<redacted>/.codex/sessions/2026/04/13/rollout-<redacted>.jsonl",
"/Users/<redacted>/.codex/sessions/2026/04/13/rollout-<redacted>.jsonl"
],
"rollout DB missing archived rows": "0",
"rollout DB model providers": "openai=<count-redacted>, spike=<count-redacted>, openrouter=<count-redacted>",
"rollout DB rows": "4274",
"rollout DB scan cap reached": "false",
"rollout DB scan error sample": [
"/Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl (rollout at /Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl has no usable header record)",
"/Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl (rollout at /Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl has no usable header record)",
"/Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl (rollout at /Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl has no usable header record)",
"/Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl (rollout at /Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl has no usable header record)",
"/Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl (rollout at /Users/<redacted>/.codex/sessions/rollout-<redacted>.jsonl has no usable header record)"
],
"rollout DB scan errors": "169",
"rollout DB sources": "vscode=<count-redacted>, exec=<count-redacted>, cli=<count-redacted>, subagent:thread_spawn=<count-redacted>, subagent:review=<count-redacted>, custom=<count-redacted>",
"rollout DB stale row sample": [
"/Users/<redacted>/.codex/sessions/2026/07/13/rollout-<redacted>.jsonl",
"/Users/<redacted>/.codex/sessions/2026/07/13/rollout-<redacted>.jsonl",
"/Users/<redacted>/.codex/sessions/2026/07/13/rollout-<redacted>.jsonl",
"/Users/<redacted>/.codex/sessions/2026/07/13/rollout-<redacted>.jsonl",
"/Users/<redacted>/.codex/sessions/2026/07/13/rollout-<redacted>.jsonl"
],
"rollout DB stale rows": "7"
},
"issues": [
{
"severity": "warning",
"cause": "rollout files are missing from the state DB",
"measured": "2 active, 0 archived",
"expected": "every rollout file has a matching threads row",
"remedy": null,
"fields": []
},
{
"severity": "warning",
"cause": "state DB rows point at missing or unusable rollout files",
"measured": "7 stale rows",
"expected": "every state DB rollout path is a file on disk",
"remedy": null,
"fields": []
},
{
"severity": "warning",
"cause": "rollout scan was incomplete or found bad files",
"measured": "169 scan errors, 0 malformed names, scan cap reached: false",
"expected": "rollout directories are fully scannable",
"remedy": "Check file permissions and unexpected files under CODEX_HOME sessions.",
"fields": []
}
],
"remediation": null,
"durationMs": 2916
},
"system.environment": {
"id": "system.environment",
"category": "system",
"status": "ok",
"summary": "OS language en-US",
"details": {
"EDITOR": "set",
"LANG": "en_US.UTF-8",
"LESS": "set",
"PAGER": "set",
"VISUAL": "not set",
"os": "Mac OS 26.5.2 [64-bit]",
"os language": "en-US",
"os type": "Mac OS",
"os version": "26.5.2"
},
"remediation": null,
"durationMs": 3
},
"terminal.env": {
"id": "terminal.env",
"category": "terminal",
"status": "ok",
"summary": "terminal metadata was detected",
"details": {
"COLORTERM": "truecolor",
"DISPLAY": "present",
"TERM_PROGRAM": "WarpTerminal",
"color output": "disabled (stdout is not a terminal)",
"effective locale": "en_US.UTF-8",
"stderr is terminal": "false",
"stdin is terminal": "false",
"stdout is terminal": "false",
"terminal": "Warp",
"terminal size": "80x24",
"terminal version": "v0.2026.07.08.17.54.stable_02"
},
"remediation": null,
"durationMs": 7
},
"terminal.title": {
"id": "terminal.title",
"category": "title",
"status": "ok",
"summary": "terminal title default",
"details": {
"terminal title activity": "true",
"terminal title items": "activity, project-name",
"terminal title project source": "cwd",
"terminal title project value": "tmp",
"terminal title source": "default"
},
"remediation": null,
"durationMs": 0
},
"updates.status": {
"id": "updates.status",
"category": "updates",
"status": "ok",
"summary": "update configuration is locally consistent",
"details": {
"cached latest version": "0.146.0",
"check for update on startup": "true",
"dismissed version": "0.121.0",
"last checked at": "2026-08-03T22:26:42.747705Z",
"latest version": "0.146.0",
"latest version status": "current version is not older",
"npm update target": "/opt/homebrew/lib/node_modules/@openai/codex",
"update action": "npm install -g @openai/codex",
"version cache": "/Users/<redacted>/.codex/version.json"
},
"remediation": null,
"durationMs": 614
}
}
}
</details>
One check is non-ok: state.rollout_db_parity, "rollout files and state DB thread inventory differ". Possibly unrelated.
What issue are you seeing?
A turn wedged inside an exec_command call that never returned, for 9h41m, until I killed the process. yield_time_ms was 30000 and never fired. The TUI kept rendering and its timer kept ticking, so the session looked healthy. Queued input was never delivered, since codex applies it between turns.
All times UTC. Thread 019fc3f6-50c0-7170-b860-ea68ac83f199. Session config: approval_policy: never, sandbox: danger-full-access, permission_profile: disabled.
At 2026-08-03T05:43:58.409Z the model issued its 2,739th exec call:
const r = await tools.exec_command({
cmd: "for n in {1..10}; do … ; sleep 5; done", // poll loop, redacted
workdir: p, yield_time_ms: 30000, max_output_tokens: 10000
});
Everything stopped at that point:
- The rollout JSONL (40,225,552 bytes, 14,036 valid records) ends on that
custom_tool_call. It holds 2,739custom_tool_calland 2,738custom_tool_call_outputrecords. One orphan, and it is this call. The file never grew again. token_countevents, 3,445 across the session, stop at05:43:56.188Z.- No terminal task or turn event. The bridge's session state stayed
inProgressfor 9h41m48s, until I killed it. - The control connection stayed open that whole time and received nothing.
The spawned child was still present in state T (signal-stopped), reparented to PID 1. SIGCONT resumed it. Its stdin was /dev/null, stdout and stderr were pipes. It had no controlling terminal, so SIGTTIN and SIGTTOU don't explain the stop.
Something external probably stopped the child, since codex doesn't send SIGSTOP. The yield should have fired regardless.
What steps can reproduce the bug?
None reliably. It appeared after 2,738 successful exec calls in a long session (15 compactions, ~518M cumulative input tokens). I couldn't trigger it deliberately on either 0.144.6 or 0.146.0.
The ordinary path is fine on 0.146.0: tools.exec_command with cmd: "sleep 240" and yield_time_ms: 5000 returned in 5.0016s. That doesn't clear much, because the ordinary path also worked for the 2,738 calls before the wedge. The retest and the process-state inspection come from my notes at the time rather than the artifacts.
Thread id for correlation: 019fc3f6-50c0-7170-b860-ea68ac83f199.
What is the expected behavior?
exec_command with yield_time_ms: 30000 should return within roughly that budget, with output or with a notice that the command is still running. A turn should not sit in-flight indefinitely with no terminal event.
Additional information
Source observation
At tag rust-v0.146.0 (commit e363b08c9175ac1cbe5893615dd2cb9ddf95043b), in codex-rs/core/src/unified_exec/process_manager.rs:
collect_output_until_deadlinecallsextend_deadlines_while_pausedat the top of its loop (line 1267).extend_deadlines_while_paused(lines 1342-1366) parks inwhile *receiver.borrow() { receiver.changed().await }, then does*deadline += paused_for, with no ceiling.clamp_yield_timebounds only the initial deadline (MAX_YIELD_TIME_MS = 30_000); the pause path can extend past it.
The shape exists in current code. Whether it caused this is another question: the flag is subscribe_elicitation_pause_state(), set when an elicitation or approval is pending. This session had approvals disabled. Nothing in the artifacts proves the flag was ever set.
Why a new issue
#29066: its comments now cover macOS, app-server transport, valid JSONL and gpt-5.6-sol, so the platform and corruption distinctions don't hold. The difference is phase. Those hangs happen after tool output exists, while waiting on model continuation. In this one no custom_tool_call_output was ever written and the child was still alive.
#22541: closest code-path relative, same field and same initial-call handling, but it covers the intentional 30s cap firing early, not an initial call that never yields. Cross-linking.
#30526: closed as a duplicate of #29066.
Suggested fix
An absolute ceiling on the initial exec_command collection, independent of pause state, so yield_time_ms is always an upper bound. Surfacing pause-state duration in diagnostics would make a stuck flag visible.
A general turn watchdog would be a separate thing, and probably belongs with #29066.