Skip to content

MCP re-init loop on Stop-hook path hangs codex exec until timeout when an MCP server fails to start (effort-correlated) #32148

Closed as not planned

Description

@4fkdgoa

What version of Codex CLI is running?

codex-cli 0.144.1

What subscription do you have?

ChatGPT (auth_mode: Chatgpt)

Which model were you using?

gpt-5.6-sol (also reproduces model-agnostically; the trigger is reasoning effort, not the model)

What platform is your computer?

Windows 11 Pro 10.0.26200 (running under Git Bash / MSYS). Node v24.13.1.

What issue are you seeing?

When a Stop hook is registered and at least one configured MCP server fails to start (e.g. a stdio server that exits non-zero at launch, or an HTTP server that needs auth), running codex exec with -c model_reasoning_effort=ultra causes Codex to hang after the model response is already printed. The model answers correctly, then Codex spins in a MCP re-initialization retry loop during shutdown and never exits — it is only killed by an external timeout (exit 124).

The observable surface is a burst of hook: Stop / hook: Stop Failed lines, but the hook scripts are not the cause (see isolation below). The real loop is Codex re-initializing the entire MCP manager on the Stop-hook path and retrying the failing server(s) indefinitely.

With RUST_LOG=info, the shutdown phase repeats this sequence dozens of times:

hook: Stop
...
WARN codex_mcp::rmcp_client: failed to initialize MCP client during shutdown:
  MCP startup failed: handshaking with MCP server failed:
  JSON-RPC error: -32600: Vault directory does not exist: c:/jexer/vault
WARN codex_mcp::rmcp_client: failed to initialize MCP client during shutdown:
  ... Auth required, when send initialize request
app_server.request{... thread/start ...}: session_init.mcp_manager_init: ...
rmcp::transport::child_process: Child exited gracefully exit code: 1
rmcp::service: input stream terminated ... serve finished quit_reason=Closed

thread/start → session_init.mcp_manager_init fires 50+ times and Child exited exit code: 1 8–9 times in a single codex exec shutdown.

Reproduction

  1. Register any Stop hook (content is irrelevant — even a script that immediately exit(0) triggers it).
  2. Have at least one configured MCP server that fails at startup. Two real examples we hit:
    • stdio: npx -y obsidian-mcp c:/jexer/vault where the vault dir does not exist → Error: Vault directory does not exist.
    • HTTP: https://mcp.figma.com/mcp while not logged in → Auth required.
  3. Run with high reasoning effort so the turn takes a while:
timeout 70 codex exec -m gpt-5.6-sol -c model_reasoning_effort=ultra \
    -s read-only "Reply with exactly: PONG-ULTRA"

Result: PONG-ULTRA prints, then the Stop-hook / MCP-reinit loop runs until the 70s timeout → exit 124. With a short/medium turn the loop sometimes finishes before the timeout, so the failure is intermittent and effort-correlated.

Isolation (what is and isn't the cause)

Three controlled runs, using exited gracefully exit code: 1 count as the loop indicator:

Change loop count conclusion
Disable the plugin providing the Stop hooks (no Stop hook) 0 a registered Stop hook is the trigger
Keep Stop hooks, replace the hook scripts with process.exit(0) stubs 9 hook script content / any subprocess it spawns is not the cause
Keep Stop hooks, create the missing vault dir (fix one failing MCP) 8 (only the auth one remains) it's the failing MCP, and each failing server contributes

Removing the failing MCP servers eliminates the loop entirely (verified: 4/4 ultra runs exit 0, zero Vault directory / Auth required in logs).

Cross-agent control

We ran the same failing stdio MCP under a different harness (Claude Code, --mcp-config with a stub that exits 1 at startup, same Stop hooks firing). It logged the identical startup failure (Connection failed ... MCP error -32000) but did not retry — it failed once and exited 0 in ~33s. So this is specific to how Codex re-initializes the MCP manager on the Stop-hook / shutdown path, not a generic MCP-startup problem.

Expected behavior

A failing MCP server should fail once (or with bounded retries) and must not block session/process termination. The Stop-hook path should not re-initialize the whole MCP manager and retry unhealthy servers unboundedly. codex exec should exit promptly after the model response regardless of a dead MCP server or reasoning effort.

Activity

  1. added
    bugSomething isn't working
    CLIIssues related to the Codex CLI
    windows-osIssues related to Codex on Windows systems
    mcpIssues related to the use of model context protocol (MCP) servers
    execIssues related to the `codex exec` subcommand
    hooksIssues related to event hooks
    on Jul 10, 2026
  2. 4fkdgoa commented on Jul 10, 2026

    @4fkdgoa
    Author

    Closing this as not-a-bug / withdrawn by reporter after further verification.

    I re-examined the original full logs (not the grep excerpts I first worked from) and ran a peer review, and the causal claims in this report do not hold up:

    • Child exited gracefully exit code: 1 and the thread/start repetitions are NOT a failing-MCP retry loop. They are Codex's normal shutdown logging. With zero failing MCP servers (both the missing-vault stdio server and the unauthenticated HTTP server removed), the same run still shows exit code: 1 ×8 and thread/start ×54 — identical to the run that still had a failing server. So the count is independent of whether any MCP fails.
    • The thread/start lines are all the same span (request_id=1) repeated as a log prefix, not 50+ distinct re-initializations. My "re-initializes the whole MCP manager and retries unboundedly" reading was a misread of the trace prefix.
    • A failing MCP server fails once (Connection failed ... MCP error -32000), not in an unbounded loop.
    • The "specific to Codex" conclusion was an overclaim: my cross-harness control was not a fair comparison (different reasoning effort, different MCP count, single run).
    • The load-bearing exit 124 symptom is not actually captured in the evidence I based the conclusion on.

    The only thing I can still substantiate is that Codex's shutdown path appears to block on MCP client teardown where another client did not — which may be worth looking at, but that is a much weaker and different statement than what this issue asserts. Rather than leave an inaccurate report open, I'm withdrawing it. Apologies for the noise, and thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingexecIssues related to the `codex exec` subcommandhooksIssues related to event hooksmcpIssues related to the use of model context protocol (MCP) serverswindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions