Xiaobai

Xiaobai

Developer · Builder

Building AI engineering systems, developer tools and long-term digital assets at XBSTACK.

About Xiaobai & XBSTACK →
Codex CLI receives response.failed, keeps waiting on the SSE transport, and surfaces idle timeout waiting for SSE instead of the original error

Why Codex CLI Turns response.failed Into idle timeout waiting for SSE: Reproduced on 0.153.4 and 0.154.0

Why does Codex CLI keep waiting after an SSE response.failed event and finally report idle timeout waiting for SSE? XBSTACK independently reproduces the behavior on 0.153.4 and the current stable 0.154.0 with a local loopback fixture, version matrix, diagnostic boundaries, and temporary handling guidance.

Published · 2026-09-124 min readXBSTACK
#Codex#OpenAI Codex#SSE#Responses API#Debugging#AI Coding Agent#Python

Why Codex CLI Turns response.failed Into idle timeout waiting for SSE

If Codex CLI ends with:

stream disconnected before completion: idle timeout waiting for SSE

do not automatically conclude that the upstream server returned nothing. XBSTACK independently reproduced a different failure shape on Codex CLI 0.153.4 and 0.154.0: the server had already sent a terminal response.failed containing a real server_error, but because the underlying socket stayed open, Codex kept waiting for EOF until the stream idle timeout fired and replaced the original failure with idle timeout waiting for SSE.

That distinction matters in production. If you keep only the final Codex error, a provider failure or capacity rejection can look like a generic network timeout, sending debugging in the wrong direction.

Result: 0.154.0 is still reproducible

XBSTACK ran the same local loopback fixture against both versions:

Codex CLIServer behaviorOriginal error preservedIdle timeout shown
0.153.4close immediately after response.failedyesno
0.153.4keep socket opennoyes
0.154.0close immediately after response.failedyesno
0.154.0keep socket opennoyes

The open-socket case exited after roughly 1.08 seconds on 0.153.4 and 1.12 seconds on 0.154.0. Those timings are not a benchmark: the fixture deliberately sets stream_idle_timeout_ms=800 so the behavior appears quickly.

The EOF case preserves the real marker:

stream disconnected before completion: XBSTACK_LOCAL_TERMINAL_FAILURE

The hold-open case instead surfaces:

stream disconnected before completion: idle timeout waiting for SSE

The SSE event sent by the server is otherwise identical.

What the fixture proves

The local server returns HTTP 200 with Content-Type: text/event-stream:

HTTP/1.1 200 OK
Content-Type: text/event-stream

It then sends a terminal failure:

event: response.failed
data: {
  "type": "response.failed",
  "response": {
    "status": "failed",
    "error": {
      "code": "server_error",
      "message": "XBSTACK_LOCAL_TERMINAL_FAILURE"
    }
  }
}

Case A closes the connection immediately. Case B leaves it open.

The resulting path is:

HTTP 200
  ↓
SSE response.failed
  ↓
Codex has already parsed a real server_error
  ↓
socket remains open
  ↓
Codex continues waiting for EOF
  ↓
stream idle timeout fires
  ↓
user sees idle timeout waiting for SSE

So the problem is not that the server was silent. The problem is that a later transport timeout can replace useful terminal-failure information.

Why this creates bad debugging decisions

If the real provider error says something like:

server_error: backend capacity unavailable

but the final Codex message only says:

idle timeout waiting for SSE

it is tempting to increase idle timeouts, add stream retries, blame DNS/TLS/proxies, reinstall Codex, or shrink context. None of those changes necessarily addresses the first failure.

Changing stream_idle_timeout_ms is therefore not a root fix. A larger value delays the replacement; a smaller value makes the replacement happen sooner.

How to tell whether your incident matches this failure shape

Keep at least four layers of evidence:

  1. HTTP status;
  2. SSE event type;
  3. response.failed.response.error;
  4. final Codex CLI error.

This sequence strongly matches the reproduced behavior:

HTTP 200
response.failed: server_error / <real message>
... socket stays open ...
Codex: idle timeout waiting for SSE

If no response.failed event arrives at all and the stream simply goes quiet, that is a different, genuine idle-timeout scenario.

Fully local reproduction

The XBSTACK reproducer requires no model or API account. It uses the Python standard library, a loopback HTTP server, and a fresh temporary CODEX_HOME for every case.

python3 repro.py \
  --codex /Applications/ChatGPT.app/Contents/Resources/codex \
  --output logs/result.json

It automatically runs:

Case A: response.failed -> EOF
Case B: response.failed -> keep socket open

and records whether the original marker is preserved and whether the idle-timeout string appears.

The EOF case records:

{
  "original_error_preserved": true,
  "idle_timeout_reported": false
}

The hold-open case records:

{
  "original_error_preserved": false,
  "idle_timeout_reported": true
}

Why 0.154.0 matters

The upstream issue was originally reported against 0.153.4, but Codex 0.154.0 shipped on September 9. A current troubleshooting page must answer the obvious question: did upgrading already fix it?

XBSTACK therefore ran the exact same fixture against the official OpenAI Codex GitHub stable release rust-v0.154.0 Apple Silicon binary.

It still reproduced.

As of September 12, 2026, under the controlled conditions above:

Upgrading to 0.154.0 is not a verified fix for this failure shape.

Future stable releases need to be retested rather than inferred from alpha builds or moving main.

The upstream issue includes a proposed patch, not an official released fix

Issue #43140 includes source analysis and a candidate patch whose core idea is to stop the producer after a terminal response.failed has already been classified instead of continuing to wait for SSE EOF.

That direction is consistent with the control experiment, but three states must remain separate:

  1. the upstream reporter tested a patch locally;
  2. XBSTACK independently reproduced the bug behavior;
  3. OpenAI merges and releases an official fix.

Only the first two are confirmed here. The issue remained open when checked on September 12, so this article does not tell users that a released version has officially fixed it.

Production handling now

Preserve the first terminal failure

For custom providers, Azure OpenAI, gateways, or proxies, keep the raw SSE event whenever possible. The first terminal error is often more diagnostic than a timeout minutes later.

Correlate provider request IDs

Store request IDs, region/capacity metadata, retry hints, and provider error categories alongside the Codex run or trace ID.

Do not blame every reconnect on this bug

This article confirms only:

terminal response.failed + socket remains open

It does not prove that all of the following come from the SSE consumer:

all server_error responses
all no healthy upstream errors
all TLS failures
all Azure capacity failures
all Codex reconnects

Treat source patches as candidate fixes until released

If you maintain a custom Codex build, the upstream patch and regression tests are worth evaluating. For production teams using official binaries, the safer release test is:

new stable release
  ↓
run the repro
  ↓
EOF case preserves original error
  ↓
open-socket case also preserves original error immediately
  ↓
then mark the issue fixed for your environment

Reliability first, security second

This is primarily a reliability and observability problem, not a reason to turn every Codex failure into a generic AI-security article.

There is still a security/governance implication: if an agent runtime replaces the real execution failure with a secondary timeout, audit trails, alerting, automatic recovery, and incident classification become less trustworthy. Accurate failure preservation is part of runtime control and incident response.

That is why this page belongs in the Codex / AI Tools Lab troubleshooting path while linking into the broader AI Agent Security themes of audit, observability, and runtime control.

Final takeaway

As of September 12, 2026, XBSTACK independently confirms:

  • Codex CLI 0.153.4 is affected;
  • Codex CLI 0.154.0 is still affected;
  • EOF immediately after response.failed preserves the original error;
  • keeping the socket open can make Codex wait until idle timeout;
  • the final idle timeout waiting for SSE can hide the real server failure;
  • changing the idle timeout is not a root fix;
  • the proposed upstream patch is not yet an official released fix.

If you are debugging Codex SSE reconnects, the first question should be: did the server already send response.failed before the timeout appeared?

For adjacent streaming failures, compare the Responses API stream-abort tool-call loss case. If you are using Astra or a custom provider, the GPT-6 Astra API guide covers the surrounding provider and migration boundaries. Runtime troubleshooting is grouped in AI Tools Lab, while authorization, audit, and runtime-control security belongs in AI Agent Security.

Primary evidence

More to Explore

Topic hub →
Vercel AI SDK 7 Migration: Tool Calls, WorkflowAgent Approval, and Stream RecoveryVercel AI SDK 7 migration with reproducible Tool Call, persistence, abort, and WorkflowAgent approval tests, including [email protected] approval-provenance evidence.ChatGPT Chat vs Work: What’s the Difference? When to Use CodexChatGPT Work vs Codex: compare Chat, Work, and Codex by task boundary, then check the latest Cloud Work, Local Chat, Mobile Remote, and Voice behavior.GPT-5.6 Review: Real Coding, Content and Data TestsGPT-5.6 review from a real Astro project: coding, content operations, Search Console and GA4 tests, failures, limits, and when Sol, Terra or Luna makes sense.Claude Sonnet 5 Hands-On: Full Process for Optimizing Oversized Astro ChunksClaude Sonnet 5 Hands-On: This article tests Claude Sonnet 5 on a real XBSTACK Astro project, using an AI coding agent to diagnose oversized chunks, the CompoundCalculator package

AI Engineering Weekly

Production changes, real failures, experiments and new XBSTACK assets.

Comments & evidence

DISCUSSION

Questions, verification and corrections

Sign in to comment. Every new comment is reviewed before publication; while pending, it is visible only to you and the administrator.

Sign-in required Reviewed before public
Loading the discussion…