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

Resolved 💬 1 comment Opened Jul 10, 2026 by 4fkdgoa Closed Jul 10, 2026

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.
  1. 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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗