Responses WebSocket stalls 300s per retry; opt-out flag removed; HTTPS fallback requires 5 failed retries
Environment: ChatGPT desktop 26.810.41047 (macOS, Darwin 25.3.0), bundled codex-cli 0.148.0-alpha.9, model gpt-5.6-sol (high/max reasoning effort), service_tier priority, ChatGPT-plan auth.
Symptom: Sampling over wss://chatgpt.com/backend-api/codex/responses goes silent mid-turn. The client detects the dead stream only via a 300s idle timeout (codex_core::responses_retry: stream disconnected before completion: idle timeout waiting for websocket; sometimes IO error: Connection reset by peer (os error 54)). Each retry cycle is a ~5-minute user-visible stall with frozen token counts.
Evidence (2026-08-14, UTC):
- Thread
01a00079-2445-7f01-a7a1-2764c376afe9: 11 stalls of 301–310s between 13:33–14:35, including four consecutive (13:59 → 14:15). - Turn
01a00191-22f6-79f1-a260-71201ed53982: exhausted retries 5/5 at 19:17. - A prior incident produced 16 five-minute reconnects across three tasks in one day.
Aggravating factors:
responses_websockets/responses_websockets_v2are stageremovedincodex features list— users cannot opt out of the websocket transport.- Built-in provider override is rejected ("model_providers contains reserved built-in provider IDs"), so
supports_websockets/stream_idle_timeout_msare unreachable. - HTTPS fallback only engages after 5 failed retries (~25 minutes of stalling).
The network here has documented upstream packet loss under load, which is presumably the trigger — but SSE-based clients on the same link detect drops and recover in seconds. The websocket transport takes 300s per detection with no user recourse.
Request: websocket-level keepalive/liveness so a dead stream is detected in seconds rather than 300s; and/or restore the transport opt-out; and/or engage the HTTPS fallback on the first idle timeout instead of the fifth.
Related: #27625, #28579
4 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Follow-up with stronger evidence that this is transport/server-side, not the local network.
2026-08-18 (ChatGPT desktop 26.810.52044, same bundled codex-cli 0.148.0-alpha.9): 33 websocket idle-timeout stall/retry cycles logged in one day — worst so far. Example chain: turn
01a0162c-a4d2-71e2-80f1-dab3f385118chit retries 1→4 at 18:47:06, 18:52:11, 18:57:19, 19:02:28 UTC (one ~5-minute frozen stall per retry), preceded by turn01a015fa-40b7-7780-b354-99e3e29fcb1bretries at 18:31:44 / 18:36:51. Allstream disconnected before completion: idle timeout waiting for websocket.The key datapoint: an automated hourly line-quality test ran at 18:32 UTC — in the middle of that stall cluster — and measured 22 Mbps up / 360 Mbps down with zero errors and 0% idle packet loss to the ISP's first hop. The local link was verifiably healthy at the exact minutes the websocket streams were stalling. (This host previously had a genuinely lossy uplink; on 2026-08-18 it tested clean all day — 14/14 hourly runs passed — while Codex logged its worst stall count yet.)
This rules out the local-network explanation for these episodes and points at the websocket path (edge terminates at DFW per
cf-ray) or upstream sampling. The 300s detection time and 5-retries-before-HTTPS-fallback turn each server-side hiccup into 5–25 minutes of frozen UI.Re-requesting: ws keepalive/liveness (seconds, not 300s), transport opt-out, or first-timeout HTTPS fallback.
Related but not the same failure mode: #39771.
We hit the same
idle timeout waiting for websocket+ silentretrying sampling request (n/5)on Desktop26.814.41407/0.148.0-alpha.15/gpt-5.6-solhigh.A localhost reverse proxy injecting unknown-type text frames (
{"type":"codex.client.keepalive"}) every 45s stopped the idle timeout. Codex loggedunhandled responses event: "codex.client.keepalive"and the same in-flight request resumed with a real tool/patch after ~8.5 min of no model text.So at least some of these 300s stalls are false dead-streams (no Responses text during high-reasoning), not packet loss. Faster dead-stream detection would have aborted a live turn. Built-in
openaistill cannot setstream_idle_timeout_ms/supports_websockets, which matches this issue.Additional sanitized prevalence data from Codex Desktop 26.818.41509 / bundled command runner 0.149.0-alpha.4.1:
A seven-day local host audit found 296 Responses WebSocket retry log entries across 175 tasks. I cannot determine billing impact from local logs and am not asserting that every retry was charged. The important operational result is that reconnect/fallback is common enough to amplify latency and agent recovery work.
This supports a session-level circuit breaker or supported transport selector: after a confirmed transport failure, switch once to HTTPS rather than repeating the same WebSocket path through the full retry budget.