[Windows][CLI 0.144.3] Codex silently exits while waiting on a tool after successful auto-compaction / PostToolUse activity

Open 💬 6 comments Opened Jul 14, 2026 by rossgeorgia0430-cyber
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

codex-cli 0.144.3, installed globally with npm.

Note: 0.144.4 was installed after these incidents. Its release notes say there are no user-facing changes, and I have not repeated the destructive workload on 0.144.4 yet.

What subscription do you have?

Pro

Which model were you using?

gpt-5.6-sol with xhigh reasoning.

What platform is your computer?

Windows 11 Pro x64, build 26100.7171
PowerShell 5.1.26100.7019
Node.js v24.11.1

What terminal emulator and version are you using?

Windows console host / Windows PowerShell 5.1, interactive Codex TUI started from a dedicated visible PowerShell window with --no-alt-screen.

Codex doctor report

Not available. codex doctor --json did not produce a JSON report in the installed CLI.

What issue are you seeing?

During long-running autonomous CLI Goals, codex.exe terminates without a final message or diagnostic record.

The parent PowerShell remains open, but both the native Codex process and npm Node wrapper disappear. The rollout ends in the middle of a tool wait. There is no panic, fatal, turn_aborted, Goal completion event, or matching Windows Error Reporting/Application Error event for Codex, Node, or PowerShell.

This happened on multiple recovery attempts:

  1. A resumed, high-context session ended while polling a running shell tool.
  2. A fresh session with a reduced MCP/app surface and an early auto-compaction threshold also ended while waiting on a shell tool.

The fresh run is the important case because auto-compaction completed successfully first. The active context dropped to about 19k tokens and was only 26,889 tokens immediately before termination. One focused test completed successfully (5 passed in 0.24s). A second shell test started, emitted 15 passing dots, and the final visible TUI status became:

Running 5 PostToolUse hooks

The process then disappeared and the console returned directly to the PowerShell prompt. The launcher's post-exit diagnostic statements did not run.

A user-level command hook was enabled for PostToolUse. Only one PostToolUse command definition exists; "5 hooks" therefore appears to be concurrent/pending hook activity, not five separate configurations. The hook is correlated with the failure but is not proven to be the root cause.

What steps can reproduce the bug?

The workload is not yet a minimal deterministic reproducer, but the controlled recovery scenario was:

  1. On Windows, enable command hooks for lifecycle events including PreToolUse and PostToolUse.
  2. Launch an interactive CLI Goal from PowerShell with a reduced configuration:
codex -C <workspace> --no-alt-screen --disable apps `
  -c model_auto_compact_token_limit=160000 `
  -c model_auto_compact_token_limit_scope=total `
  -c mcp_servers.<unrelated-server>.enabled=false `
  "<long autonomous task>"
  1. Let the Goal use three subagents and overlapping shell-tool calls.
  2. On the root agent, run a test/tool command that exceeds the initial tool yield and launches ordinary PowerShell subprocesses.
  3. Let Codex poll/wait for the running tool while subagent tool calls complete.
  4. Observe the TUI reach Running 5 PostToolUse hooks, then return directly to PowerShell with no final rollout event.

Sanitized hook configuration:

{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "<node> <third-party-hook.js>",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

The active unit tests that could invoke WMI/detached-process behavior were explicitly skipped. The executed code used ordinary PowerShell subprocesses.

What is the expected behavior?

Codex should remain alive until the tool and hooks finish.

If a tool, hook, subprocess, compaction step, or process-group operation fails, Codex should:

  • record the failing component, exit code, timeout, stderr, and termination reason;
  • isolate hook cancellation/failure from the parent CLI process;
  • preserve the tool as a recoverable pending/unknown state;
  • emit a terminal failure/aborted event instead of silently ending;
  • allow an active Goal to reattach without leaving ambiguous partial state.

Additional information

Confirmed:

  • Early auto-compaction worked in the fresh session.
  • Context exhaustion cannot explain the fresh post-compaction termination by itself.
  • The rollout ended during the long tool wait without a matching result.
  • codex.exe and the Node wrapper disappeared while the launcher PowerShell remained.
  • No matching WER/Application Error, Resource Exhaustion event, panic, or fatal log exists.
  • No pytest/build process remained afterward.
  • Disabling hooks for a single invocation is accepted and leaves Goals, MCP, and multi-agent features available.

Hypotheses, not confirmed root causes:

  • A Windows race/unhandled exit path involving hook fan-out, long-running tool polling, and child process/job/console-control handling.
  • The console behavior is compatible with a control-event interruption, but no exit code or dump was produced, so STATUS_CONTROL_C_EXIT is not claimed as confirmed.

Impact:

This repeatedly interrupts multi-hour autonomous tasks, leaves a dirty working tree and durable Goal ledger partially advanced, and requires manual fencing/reconciliation before safe continuation.

Related but not duplicate:

  • #18067: large hook payloads fail silently on Linux/Windows.
  • #21753: hook parity tracker notes incomplete PostToolUse, subagent, compaction, and cross-surface behavior.

I can provide sanitized rollout excerpts, exact timestamps, process-tree snapshots, Windows event exports, and session IDs privately to OpenAI maintainers. The complete rollout is not attached publicly because it contains proprietary repository paths, prompts, and source context.

View original on GitHub ↗

6 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #31930

Powered by Codex Action

rossgeorgia0430-cyber · 1 month ago

Sanitized diagnostic evidence (2026-07-14)

This comment adds the smallest useful evidence set without publishing private workspace paths, source text, prompts, account data, or full session identifiers.

Observed timeline (local time, UTC+08:00)

  • 13:13:51 — Codex CLI 0.144.3 session started on Windows 11 Pro x64 (build 26100.7171).
  • The session successfully auto-compacted at approximately 13:29:09.
  • last pre-compaction total: 156,357 tokens
  • first post-compaction total: 18,989 tokens
  • latest recorded total before exit: 26,889 / 258,400
  • The CLI then ran a focused Python test. The terminal showed test progress but no final test result.
  • Immediately before returning to the PowerShell prompt, the TUI displayed Running 5 PostToolUse hooks.
  • 13:30:53 — an external sentinel confirmed that both the Codex native process and its Node launcher had disappeared. The outer PowerShell launcher was still alive.
  • The rollout stopped being written at 13:30:24.

Negative / exclusion evidence

  • No turn_completed, turn_aborted, panic, fatal error, or Goal terminal event was written.
  • No relevant Codex/Node Windows Error Reporting, Application Error, or Resource Exhaustion event was present in the matching time window.
  • The successful compaction and low post-compaction context usage make context exhaustion an insufficient explanation for this exit.
  • The wrapper command after Codex did not run, so the original run did not preserve an exit code.

Hook configuration relevant to this run

  • One global PostToolUse command was configured (PowerShell -> a local Node hook), with a 30-second timeout.
  • Project-level SessionStart and Stop hooks were also configured.
  • The TUI's “5 PostToolUse hooks” therefore appears to represent multiple pending/running hook invocations, not five separate configured hook definitions.

Current mitigation / comparison run

I upgraded the CLI to 0.144.4 and started a fresh recovery session with per-process flags:

  • hooks=false
  • goals=true
  • multi_agent=true
  • optional Apps disabled
  • only one required MCP instance enabled

That comparison session successfully created a new rollout and an active Goal. I will update this issue if it exits in the same way.

Root-cause confidence

The evidence is compatible with a Windows process/control-event or hook/tool-wait lifecycle race, but it is not sufficient to claim an exact exception code or a single hook implementation as the cause.

The raw rollout and local logs contain private project paths, source fragments, and prompts, so I am not attaching them publicly. I can provide a further-sanitized excerpt or original files through a maintainer-provided private channel.

rossgeorgia0430-cyber · 1 month ago

Follow-up: reproduced on 0.144.4 with Hooks disabled; Goal continuation survived (2026-07-14)

A second sanitized observation materially narrows the earlier hypothesis.

Isolation configuration

The recovery run used Codex CLI 0.144.4 with per-process configuration:

  • Hooks disabled
  • optional Apps disabled
  • Goals enabled
  • multi-agent enabled
  • one required MCP server only
  • auto-compaction threshold reduced

Result

  • The CLI created an active Goal and ran normally for about 83 minutes.
  • At 15:27:05 local time (UTC+08:00), the external sentinel observed the CLI/native process and Node launcher had exited before Goal completion.
  • The unified terminal session returned exit code 1.
  • No matching Windows Application / WER event was found.
  • The rollout's last write immediately around CLI exit was 15:26:51.

Important continuation behavior

The same Goal did not stop. Codex App's app-server subsequently continued the same rollout and protected project ledger:

  • the rollout was actively written again after the CLI process had disappeared;
  • Goal status remained active;
  • protected ledger event count advanced from the recovered baseline to more than 400;
  • lease recovery and focused-test receipts continued to be recorded.

This is useful positive evidence for Goal durability, but it also means the CLI exit is not explained solely by the previously configured third-party PostToolUse hook, because Hooks were disabled for this process. It also reproduced with only one MCP server.

The remaining evidence is more consistent with a broader Windows CLI/PTY/process-lifecycle failure than with context exhaustion or a specific hook implementation. I am retaining the local sentinel receipt and can provide it through a private maintainer channel.

shleder · 14 days ago

The fresh-run evidence here is especially useful: auto-compaction completed, context was low, then Codex disappeared while waiting on a shell tool and the rollout ended with no result or terminal event.

That is a strong unfinished-tool-call recovery test. Codex Rescue is local-first and does not assume whether the test or PostToolUse hook finished. It keeps the original rollout untouched, does not replay the command, and preserves unknown side effects for manual review.

If you still have that rollout, could you run:

pipx install codex-rescue==0.1.0a3
codex-rescue sessions
codex-rescue doctor --latest

Sanitized diagnostic output only is sufficient—please don’t publish the rollout, hook commands, repository data, prompts, paths, databases, or secrets.

https://github.com/shleder/codex-rescue

rossgeorgia0430-cyber · 12 days ago

Status update + Codex Rescue results (2026-08-16)

Thanks — the rollout is preserved. I ran codex-rescue 0.1.0a3 against it, plus a
regression sweep over every rollout I have since the incident. Sanitized output only.

1. Codex Rescue on the original incident rollout

Run read-only (doctor, no salvage) against the preserved 0.144.3 root rollout:

status:   UNKNOWN_OPERATIONAL_SCHEMA
findings: UNKNOWN_OPERATIONAL_SCHEMA, UNFINISHED_TOOL_CALL, REPO_STATE_DIVERGED

compacted:                          true
operational_events_after_compaction: 31
valid_record_count:                 289
recoverable_prefix:                 true
unfinished_tool_call_count:         1
unfinished_tool_calls[0]:
    tool_name: wait
    family:    function_call
    arguments: {"cell_id":"<id>","yield_time_ms":30000,"max_tokens":4000}

This independently reproduces the report from the rollout alone: compaction
completed, 31 further operational events were written, and the session then ends
holding exactly one unfinished wait call — i.e. Codex died while polling a
running shell cell, not while starting or finishing one. recoverable_prefix: true,
and the tool left the original untouched, as documented.

Thread topology at death (from the rollouts, not from Rescue): the root TUI thread
and all three subagent threads terminated within the same ~20-second window, each
mid-tool-call. A simultaneous whole-process-tree death is more consistent with a
process/console-level event than with per-thread tool logic.

2. Two Codex Rescue issues worth fixing

Both are tool-side, not Codex-side:

  • UNKNOWN_OPERATIONAL_SCHEMA is a false positive here. The only flagged record

is a valid event_msg / mcp_tool_call_end payload, which the parser does not
recognize. It fires on healthy current-format sessions too (see below), so on
today's rollouts it masks the real status — the genuinely interesting finding
(UNFINISHED_TOOL_CALL) gets outranked by a parser gap.

  • REPO_STATE_DIVERGED fires unconditionally on non-git workspaces. The

workspace is SVN, so gitstate fails with fatal: not a git repository and the
result is reported as divergence rather than "VCS not supported / unknown".
confidence: unknown is set correctly in the JSON, but the top-line finding does
not reflect that.

3. Regression status: not reproduced since 0.145.x

Scanning every local rollout for the failure signature — session ends with an
unresolved tool call and/or no terminal event (task_complete / turn_aborted):

| Window | Versions | Rollouts | With compaction | Signature hits |
|---|---|---|---|---|
| Incident, 2026-07-14 | 0.144.3 | — | yes | 4 (root + 3 subagents) |
| 2026-07-14 → 07-16 | 0.144.4, 0.144.2 | — | yes | 2 |
| 2026-07-17 → 08-08 | 0.145.0 → 0.147.0-alpha | 208 | 169 (2,456 compaction events) | 0 |

In the clean window: 21 active days, 176 rollouts with subagent activity, and every
single rollout terminates with an explicit event (197 task_complete, 11
turn_aborted) — no silent ends at all.

Exposure was maintained, so this is not survivorship bias from a changed setup:
command hooks stayed enabled throughout (features.hooks = true, with
PostToolUse plus PreToolUse/SessionStart/UserPromptSubmit/Stop/
PermissionRequest continuously configured across that period), long autonomous
runs continued, and auto-compaction fired heavily.

Caveat on what this can and cannot prove. Rollout forensics cannot distinguish
"the CLI never exited" from "the CLI exited and the app-server resumed the same
rollout cleanly" — which is exactly what happened in my second (0.144.4) report,
where the rollout ended at a clean tool boundary. So I can state that the
unfinished-tool-call silent-exit signature has not recurred, and that no rollout
in the clean window ends without a terminal event; I cannot claim from this data
alone that no CLI process ever exited unexpectedly. I no longer run the external
process sentinel that caught the original exit, and I have not deliberately re-run
the original destructive workload as a targeted reproducer.

Given no recurrence across that window, I am fine with this being closed as stale
unless maintainers want it kept open pending a deterministic reproducer. If it
returns I will reopen with sentinel data.

shleder · 3 days ago

Your interrupted wait reproduction is preserved in the Rust adapter as bounded UNFINISHED_TOOL_CALL correlation; no tool call is replayed.

Migration update: active Codex Rescue development has moved to Vetto: https://github.com/shleder/vetto. The standalone shleder/codex-rescue repository remains public as compatibility history. User installation is now npm install --global @shleddy/vetto@next, with recovery under vetto rescue. The boundary remains read-only/copy-only and does not modify session JSONL or vendor SQLite. The newest diagnostic changes are merged into Vetto main and will be included in a later npm alpha; no source install is requested.