AIFreeAPI Logo

Codex Timed Out: Find the Stalled Stage Before Retrying

A
6 min readOpenAI Codex

A timeout tells you that one wait ended, not which system failed. Preserve the work, identify the stalled stage, and make the next test answer one question.

A developer workstation tracing a Codex timeout across connection, initialization, MCP, tool, process, and stalled-turn stages before one bounded retry

A Codex timeout is a stopped wait, not a root-cause diagnosis. It may occur before a session connects, while an app or extension initializes, while an MCP server starts, during one tool call, while a child command exits, or after a long turn stops producing progress. Those failures can look similar from the composer, but they have different owners and different safe recovery actions.

Start by preserving the state you already have. Do not launch several duplicate sessions, delete .codex, rotate credentials, change the model, switch networks, and disable tools at the same time. Record the exact visible message, the Codex surface and version, local time and timezone, the last completed action, and whether files changed. Redact tokens, email addresses, private prompts, and repository content before sharing the record.

The most useful first question is: what was Codex waiting for when the timer ended?

Name the stalled boundary

Use the last confirmed progress, not the word “timeout,” to classify the incident.

Last observable stateLikely boundary to inspectFirst bounded check
The app, CLI, or extension never became readyClient initialization, authentication, or connectionCompare one clean launch with the same account and project
“Connecting” or repeated stream reconnectsTransport, proxy, VPN, remote-host network, or service routeTest the same surface once on the same route; do not infer from browser access
An MCP server failed during startupLocal process/command or remote MCP initializationRun codex mcp list, then inspect that server's command or URL
One MCP tool exceeded its waitTool execution, downstream service, or payload sizeCall the smallest read-only operation on that same server
A shell command kept running or would not exitChild process, interactive prompt, watcher, or cleanupInspect the command's own output and process behavior outside a large Codex turn
The turn stayed active but showed no new progressModel request, tool loop, approval, context, or client displayCheck session state and the last emitted action before resuming
The terminal message includes HTTP 429Usage, project, workspace, or provider limitUse the separate Codex 429 diagnostic

A browser page loading successfully does not prove that a sandboxed command, IDE extension host, Remote SSH machine, container, or MCP process can reach the same destination. OpenAI's sandbox documentation separates approval behavior from the filesystem and network resources available to commands. “No approval appeared” and “the network path exists” are therefore different claims.

A six-stage Codex timeout map matching each stalled boundary to its likely owner, first bounded check, and a small before-state record
A six-stage Codex timeout map matching each stalled boundary to its likely owner, first bounded check, and a small before-state record

Capture a small before-state

Keep the record short enough that a second run can be compared with it:

  • Codex surface: desktop app, CLI, IDE extension, cloud, or remote control;
  • installed client version and operating system;
  • authentication route: ChatGPT sign-in, direct API key, or custom provider, without the secret;
  • project location: local, worktree, container, WSL, or remote host;
  • exact error and timestamp, plus a request or session ID if shown;
  • active MCP server or child command at the last progress point;
  • files changed and whether the process is still running;
  • one relevant configuration fact, not the entire config file.

In the CLI, the current developer commands reference documents /status for session configuration and token/context usage. It also documents /debug-config for effective configuration layers and policy sources, and codex login status for the active authentication mode. These checks answer different questions. /status is not a network test, and a successful login status does not prove that an MCP endpoint is reachable.

If your installed build does not expose a command, use codex --help and the controls visible in that client rather than copying flags from another release.

Treat MCP startup and tool execution as different timers

For MCP configured on a Codex host, OpenAI documents two separate controls:

toml
[mcp_servers.example] command = "example-mcp" startup_timeout_sec = 20 tool_timeout_sec = 90

According to the official MCP configuration guide, startup_timeout_sec defaults to 10 seconds and covers server startup; tool_timeout_sec defaults to 60 seconds and covers one tool run. This distinction prevents a common misdiagnosis: a server that cannot initialize is not repaired by giving every tool more time, and a slow downstream operation is not explained by the startup limit.

The documented MCP startup wait and per-tool call wait shown as separate timers with the conditions under which increasing either timer is justified
The documented MCP startup wait and per-tool call wait shown as separate timers with the conditions under which increasing either timer is justified

Increase a timer only when you can show that the same operation completes correctly but slightly later than the current boundary. Before changing it, check the ownership:

  • for a local STDIO server, verify that its executable exists, starts with the configured environment, and does not wait for interactive input;
  • for a streamable HTTP server, verify the exact URL, authentication route, and reachability from the Codex host;
  • for a tool timeout, reduce the input to the smallest read-only call and inspect the server's own logs or request ID;
  • for a crash or hang, fix the process rather than converting a fast failure into a longer wait.

The desktop app, CLI, and IDE extension can share MCP configuration on the same Codex host. That does not mean they share every process environment, remote host, or UI state. Note where the failing server actually runs.

Separate a child-process wait from a Codex request

A command can exceed a wait even when the Codex connection is healthy. Common examples are a development server designed to stay open, a test watcher, a script waiting for stdin, a subprocess that inherited an open handle, or cleanup that never finishes.

Reproduce the command directly in the same working directory and environment. Ask three concrete questions:

  1. Does it produce output or a listening address?
  2. Is it designed to terminate on its own?
  3. Does it wait for input that the Codex run cannot provide?

If it is a long-lived service, run it as a deliberately managed background process and test readiness separately. If it should exit, use its logs and exit behavior to find the stuck child. A larger Codex timeout only hides that distinction.

Resume without destroying the explanation

When the client still has the session, prefer resuming over starting a blind duplicate. The official command reference documents codex resume for interactive sessions and codex exec resume for eligible non-interactive sessions. Resume can preserve conversation context, but it does not guarantee that an interrupted external tool call is idempotent. Before repeating a write, check the repository, cloud job, or remote service for partial completion.

Make the recovery test deliberately small:

  1. stop or account for any duplicate background work;
  2. keep account, route, model, and project constant;
  3. change only the condition supported by evidence;
  4. run one read-only or easily reversible action;
  5. compare its last progress point with the original record.

If the small test succeeds, expand gradually. If it stops at the same stage, collect the smallest reproduction and the relevant request, session, server, or process ID. If the evidence instead shows permissions, config precedence, or command network boundaries, continue with the Codex sandbox and config guide. If it shows 429, credits, or a usage window, keep that diagnosis in the rate-limit path.

The durable fix is not “wait longer.” It is to identify the wait that ended, prove which boundary owns it, and make the next run test only that boundary.