Codex Desktop: gpt-5.5 xhigh turn stalled 30m before first output, then resumed normally
Summary
A Codex Desktop turn using gpt-5.5 with xhigh reasoning remained user-visible as Thinking for more than 30 minutes before the first persisted assistant/reasoning item appeared. Once the first item appeared, the turn continued normally with assistant text and tool calls within seconds.
This looks different from ordinary slow generation: the local rollout has no assistant/reasoning/tool event during the gap, and normal persisted logs did not retain a useful stream/retry diagnostic for the missing interval.
Environment
- Product: Codex Desktop on Windows 11 with WSL2 Ubuntu workspace
- Desktop package observed in logs:
OpenAI.Codex_26.519.5221.0 - Desktop release string observed in logs:
26.519.41501 - WSL app-server binary:
codex-cli 0.130.0-alpha.5 - Model:
gpt-5.5 - Reasoning effort:
xhigh - Workspace type: WSL project
Primary observed case
All timestamps below are UTC.
- User submitted turn:
2026-05-23T16:09:18.281Z - First persisted assistant/reasoning item:
2026-05-23T16:39:56.682Z - Pre-first-output gap: about
30m38s
First persisted output sequence after the stall:
2026-05-23T16:39:56.682Z response_item reasoning
2026-05-23T16:39:57.612Z event_msg agent_message
2026-05-23T16:39:57.612Z response_item message assistant
2026-05-23T16:40:08.580Z response_item function_call
2026-05-23T16:40:08.726Z response_item function_call_output
2026-05-23T16:40:08.727Z event_msg token_count
User-visible behavior: the thread sat on Thinking for the entire gap. When it finally resumed, it did not appear to replay a backlog; it just began producing the first reasoning/message/tool items at normal cadence.
Secondary same-day signal
In another thread on the same Desktop session, the UI visibly showed Reconnecting... 2/5 while still in Thinking on gpt-5.5/xhigh. That shorter case had about a 41.6s gap before first reasoning output, but the local Desktop app-server transport logs did not show a corresponding app-server reconnect/restart.
This may be related to existing reconnect/stream issues, but the important gap here is observability: the visible reconnect state and the long pre-first-output stall are not represented clearly enough in the durable rollout/log artifacts.
Historical local scan
I scanned local rollout JSONL files for the same host, using time from user submission to first assistant/reasoning/tool item. Private transcripts and paths were not included in this report.
High-level results:
rollout files scanned: 305
completed turns with usable timing: 7618
gpt-5.5 / xhigh: n=168, p95=1m11s, max=30m38s, >=120s=3, >=300s=1, >=600s=1, >=1800s=1
gpt-5.5 / high: n=496, max=3m13s, >=120s=2
gpt-5.5 / medium: n=347, max=1m55s, >=120s=0
gpt-5.5 / low: n=120, max=1m07s, >=120s=0
codex-auto-review / low: n=6452, max=0m48s, >=120s=0
This suggests the 30m+ outlier is strongly associated with gpt-5.5 + xhigh in this local sample, though it does not prove the issue is exclusive to xhigh.
Expected behavior
- A turn should either start streaming within the normal startup range, or surface a durable diagnostic/error state if the response stream is idle/retrying for many minutes before first output.
- If the UI shows reconnecting/retry state, the durable logs/rollout should retain enough information to distinguish model queueing, websocket retry, backend stall, app-server transport reconnect, and local UI state races.
Actual behavior
- UI remained on
Thinkingfor30m38sbefore the first persisted output item. - The turn eventually resumed normally, making it look like the request was alive but silent for the entire interval.
- A shorter same-day case showed visible
Reconnecting... 2/5, but there was no matching Desktop app-server reconnect/restart in local logs.
Related issues
Possibly related, but not exact duplicates:
- #18471:
Reconnecting...visible while app-server transport appears connected - #20739: Responses WebSocket closes before
response.completed - #21360: Desktop sessions stuck in thinking/generating lifecycle stalls
22 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Follow-up after reviewing the duplicate bot chain:
The bot linked #24045, and that issue links to #22634. Those are useful but do not look like exact duplicates of this report.
What overlaps:
Reconnecting...during the pre-output stall;responses_websocketretry/fallback behavior before HTTP/SSE succeeds;5 x 15s = 75sbefore fallback.What differs in this report:
gpt-5.5with Extra High reasoning, and the user has seen the symptom more often on xhigh, though that correlation is not proven;Thinking.So #24045/#22634 are relevant for the reconnect/transport part of the symptom, but they do not fully explain the long pre-first-token stall. A useful next diagnostic would be to correlate the stall window with local transport logs: whether it was WebSocket retry/fallback, no stream events at all, a backend sampling request in progress, or renderer-side loss of visible stream ownership.
Additional evidence from local Desktop logs plus the persisted session JSONL narrows this down:
That is a 1,838.5 second gap between turn context/user message persistence and first reasoning/output item. Nearby turns in the same logs had much smaller pre-output gaps, roughly 25-40 seconds, including other
xhighturns.During the gap the Desktop log shows focus/config/plugin-list activity and repeated bundled-plugin reconcile failures, but no evidence that the original turn was not submitted. In the same Desktop log aggregate counts were:
broadcastFallback=true: 0targetDestroyed=true: 0content-tracing: started during the stall at16:24:23.298ZSo this looks less like a client-side failure to enqueue/submit and more like a model/backend/turn-runtime stall before the first streamed response item. The client kept the turn route open and eventually received normal output without user retrying the same turn.
One possible confounder visible in the same log: the Desktop repeatedly attempted bundled plugin reconciliation and failed with a WSL/Windows path translation issue like
C:\mnt\c\...\plugins\cache\...; I am not claiming that caused this stall, only noting it as concurrent background noise in the repro window.🔧 Complete Solution Submitted
Root Cause
A Codex Desktop turn using
gpt-5.5withxhighreasoning stalled for 30m38s before the first persisted assistant/reasoning item appeared. The key evidence:response_routed method=turn/start durationMs=4Key Fixes
Testing Strategy
Files
Full solution document:
codex-24260-gpt55-turn-stalled-30min-fix.md---
Submitted via automated solution pipeline. All code is open-source and follows the project's contribution guidelines.
I am seeing the same class of pre-first-output stall on macOS, and it is not limited to a long context, the Desktop UI, or a single model/reasoning setting.
Environment:
codex-cli 0.133.026.3.1 (a), build25D771280aarm64responses_http,api.path="responses"gpt-5.5andgpt-5.4User-visible behavior:
Thinking/Working.continuecan resolve the same task in a few seconds.Local log evidence from
~/.codex/log/codex-tui.logshows long idle time inside the Responses streaming client, while local busy time is tiny:This looks like the request is accepted but the stream can remain silent before the first useful event, without a user-visible error or an aggressive first-event timeout. The important diagnostic signal is that
time.busyis only milliseconds whiletime.idleis hundreds of seconds.Related earlier issue:
gpt-5.4andgpt-5.3, but that issue is now closed and locked.Request:
responses_http.Cross-thread synthesis after following the issue timeline/cross-reference events, not just ordinary comments.
I think this cluster is sharper if it is treated as several different waits that currently collapse into the same user-facing
Thinking/Working/Reconnectingstate.Related public reports I found useful:
Thinkingfor minutes even on simple prompts.Workinghangs plus reconnect attempts; interrupt/resubmit can make the same prompt run normally.pwd,rg --files) returned instantly, then the app sat for minutes with no next assistant action until interrupt. This looks like a post-tool continuation stall, not a slow local tool.stream disconnected before completion: Transport error: network error: error decoding response body.External threads are especially useful because they expose implementation-level hypotheses/workarounds:
openai-codex/gpt-5.5hangs with no streamed text, no tool call, and aborted assistant turns with empty content / zero recorded usage. Same thread has useful narrowing from @mitsuhiko, @51616, @ty91, and @IgorWarzocha: tiny prompts can intermittently stall before output; forcingssedid not eliminate stalls; long-context sessions show repeated ~300s gaps after tool results; region/routing may matter; and hidden retry/429 behavior may be involved.https://chatgpt.com/backend-api/codexin ~10ms, then no response for 10 minutes before client disconnect/retry. @OverHash also reproduced the problem in regular Codex CLI by forcingsupports_websockets = false, which is important because it means this is not only an OpenCode bug. @Stellarthoughts, @balaji-dutt, @rickchristie, and others added SEA/Oceania/region anecdotes, with VPN sometimes helping but not universally.stream stall timeouttimings around 464s / 486s / 789s. @quanla93 then referenced this issue from quanla93/9router@d03cd05bda16e43a65b877b6e7e6e794551d1de5, which adds a 60s first-token watchdog and retries when the stream opens but no first chunk arrives.executor.execute()is still waiting for the initial upstream response, before there is any response body to race. That PR explicitly says it is complementary to the TTFT/first-token timeout because it covers the earlier phase wherefetch()has not returned yet.response.completed.My current RCA framing:
You have hit your ChatGPT usage limitimmediately, while retries/WebSocket can produce “nothing happens for a very long time.” That makes retry-after / 429 handling worth instrumenting. Possibly related: openai/openai-node#1840.Durable fix suggestions:
Thinking:websocket_connect_start/end,websocket_prewarms, retry count, fallback activation.Retry-After, selected transport, region/POP if available, request attempt id.full_context_window_limit_reached/token_limit_reachedalongside the phase timings. That would help distinguish “huge context made model slow” from “request/stream was idle before any event.”The most useful near-term maintainer test might be to add phase timing around the ChatGPT-backed Codex request path and compare four cases:
supports_websockets = false);The key thing to prove is exactly where the wall-clock gap sits: before initial response, after stream open but before first event, after tool result but before the continuation request/event, or inside WebSocket retry/fallback. Right now all of those can look identical to users.
Follow-up after tracing the exact
response.completedWebSocket signature through current source, recent linked issues, and the Desktop state/restore reports.I think the useful framing is no longer "one slow Thinking bug." It looks like two coupled bug families plus missing phase telemetry:
Those then collapse into the same user-facing
Thinking/Working/Reconnectingstate, which makes reports look contradictory even when they are probably adjacent parts of the same failure surface.Current source-level mapping
I checked current
openai/codexmainon 2026-05-26 through the GitHub API.The exact UI/string in the newer reports:
maps directly to the Responses WebSocket path:
codex-rs/codex-api/src/endpoint/responses_websocket.rsrun_websocket_response_stream(...)sends the request, then waits ontokio::time::timeout(idle_timeout, ws_stream.next()).idle timeout waiting for websocket;websocket closed by server before response.completed.codex-rs/model-provider-info/src/lib.rsDEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000DEFAULT_STREAM_MAX_RETRIES = 5DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS = 15_000codex-rs/core/src/responses_retry.rshandle_retryable_response_stream_error(...);Reconnecting... 2/5;codex-rs/core/src/client.rstry_switch_fallback_transport(...)/force_http_fallback(...)permanently disables WebSockets for that Codex session and resets WebSocket state.codex-rs/core/tests/suite/websocket_fallback.rsThis source path explains a lot of public reports:
Reconnecting... 2/5being the first visible reconnect is expected from the code, not user misreporting.5 x 15s ~= 75sstartup stalls in #22634 / #24045 line up with WebSocket connect timeout and retry budget.websocket closed by server before response.completedin #18960 / #19703 / #20739 / #22156 / #24533 is the literal close-before-completed path, not a generic UI warning.Public issue graph that now looks connected
Transport / WebSocket / stream close cluster:
stream disconnected before completion/websocket closed before response.completedreports.Reconnecting... 2/5..5/5.Transport error: network error: error decoding response body, likely same user-facing retry machinery but not necessarily the exact WebSocket close path.Silent/stuck generation cluster:
Thinking/Working, sometimes fixed by interrupt/resubmit.Desktop/renderer/session-state cluster:
Reconnecting...can appear even when the app-server transport remains connected; logs showturn/started for unknown conversation.markedStreaming=true.unknown conversation, title-generation timeout, or fresh/recreated conversation state issues.Item not found in turn state.My read: the WebSocket stream failures are real, but the persistent "stuck forever / phantom work / missing messages / stop does not work" symptoms need the Desktop state cluster to explain them.
Likely RCA buckets
1. WebSocket connect or protocol path failure
Some users fail before or during WebSocket use:
1008) after upgrade;15s;response.completed.Likely fixes:
disable_responses_websocket/prefer_httpoption instead of requiring custom provider overrides.WebSocket connect timed out,server closed before response.completed,HTTP fallback active, etc., instead of one generic reconnect loop.2. Stale or reused WebSocket waits too long for first event
#23807 is especially useful here. The source currently uses the same 300s stream idle timeout while waiting for the next WebSocket event after request send/reuse. If the reused connection is stale, half-open, or server-side dead, the client can sit for exactly 300s before retrying. That looks exactly like the #23807 5-minute post-tool gaps.
Likely fixes:
first_event_timeoutfromstream_idle_timeout.last_request/last_response_rxmore aggressively after errors, close frames, cancellation, or renderer/app-server reconnect.3. Request accepted but no first output/event for many minutes
This issue and @zcyyyds-test's comment show stalls that also occur over
responses_http, so WebSocket fallback is not the full story. A request can be accepted and then sit for minutes before the first persisted reasoning/message/tool item.This needs separate instrumentation for:
response.completed;Retry-After/ rate-limit event, if any.Likely fixes:
running remotely / reconnecting to accepted turnrather than ordinaryThinking.4. Retry/fallback can create phantom or duplicate work
If the client does not know whether a request was accepted, retrying the full prompt can create hidden work or later out-of-order state. That matches reports where messages looked unsent, work continued invisibly, or restarting caused missing messages to reappear.
Likely fixes:
cancelled,still running remotely,unknown, orfailed to cancel, rather than leaving the user in a pseudo-streaming state.5. Desktop renderer/session-state recovery is not authoritative
The Desktop issues are probably a separate but coupled bug family. Transport failures, renderer reloads, app restart, and interrupts expose a state machine problem:
markedStreaming=true;turn/startedor item events for an unknown conversation;turn/completeddoes not appear sufficient to repair a renderer that missed prior item events;Item not found in turn state.Likely fixes:
completed,failed,interrupted) as authoritative on resume. A terminal turn should not rehydrate as streaming.turn/started/ item events for a short window while conversation state is being hydrated instead of immediately dropping them as unknown.turn/completed, or add a cheapthread/turns/items/listreconciliation path for active/recent turns.Why
supports_websockets = falseis only a partial workaroundIt can avoid the WebSocket-close / 75s startup / 300s stale-WebSocket parts of the problem, and it is useful for users with bad WS routes. But it does not fully cover:
markedStreaming=true,unknown conversation, and missing turn items;So "force HTTP/SSE" is a practical mitigation, not a complete RCA.
Practical user workarounds while this is being fixed
Reconnecting... 2/5..5/5, try forcing HTTPS/SSE via a provider override with WebSockets disabled, where available. A first-class config flag would be much better.codex doctor --alland test IPv4 vs IPv6 reachability if WebSocket connect timeouts are consistent. #23434 suggests IPv6 route preference can matter.Reconnecting... N/5state plus sanitized local log snippets are useful. The UI error text may not survive in durable Desktop logs.Minimal maintainer test matrix
I think one focused integration matrix would isolate most of this:
response.completed;turn/completed;For each case, assert:
markedStreaming=true;Short version
The exact WebSocket error reports are real and source-explained. The long 5-minute and 75-second variants are also source-explained by current defaults. The 10-30 minute no-output cases and the post-restart phantom/stale UI cases require additional explanation: either backend/request/first-event stalls on HTTP/SSE too, plus Desktop state recovery bugs that keep terminal turns visually alive or lose item state.
The durable fix is probably not one timeout tweak. It is:
Interesting report 👀
The part that stands out is that the session eventually resumed normally after a ~30 minute silent gap.
That feels less like a pure model-generation slowdown, and more like a “turn orchestration / runtime state” issue somewhere between:
Especially because there were no persisted reasoning/tool events during the stall window.
In mixed-runtime agent systems we've been seeing a similar pattern:
sometimes the expensive part is not inference itself, but the coordination layer waiting on internal state transitions that never fully fail, yet also never fully advance 😅
The “alive but silent” state is particularly nasty for observability because from the user side it looks identical to:
Your local timing analysis is actually super valuable here ✨
The p95 vs 30m outlier comparison helps separate “normally slow xhigh” from “something entered a pathological runtime state”.
Really good investigation.
Your comment is a lot of yap and presumably AI slop, but I experienced a HTTP 504 returned (and it looked to be by Cloudflare, rather than OpenAI servers) after precisely 30 minutes of an HTTP call that had no response (i.e., 30 minutes until TTFB response). I presume this is what OP experienced.
Sometimes OpenAI servers have responded in less time, one time it was 22 minutes for me.
Session: 019e6935-846f-7402-a8ad-7973d2e54db2
ничего не прмогает подписка идет компесации нет!!! байкот и переход на антропик
Strong +1 to @MisterRound's bucket #2 ("stale or reused WebSocket waits too long for first event") — we hit exactly this on codex-cli 0.133.0 (app-server mode, gpt-5.5, responses_websocket transport, ChatGPT-subscription auth), and have a packet capture that confirms the mechanism on the wire, not just from source.
When a turn stalled, the app-server emitted turn/started and then no events. The pcap shows codex pushed the request onto a pooled connection the server had already closed, and got an immediate RST:
So the connection wasn't slow or the backend silent — the server actively reset a reused idle connection, and codex did not fast-fail on the RST. It kept waiting for a stream event that could never arrive. On runs we let proceed without intervention, recovery came at the ~300s mark, and the codex_core::client span closed with:
time.idle=304s lines up exactly with the DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000 you found — i.e. a RST on a reused connection isn't surfaced as an immediate connection error; it
falls through to the full 300s idle timeout before the retry fires. That's direct evidence for your suggested fixes: verify liveness / avoid reuse after idle, and split a short first_event_timeout from the 300s stream_idle_timeout (or treat a TCP RST as a fast retry trigger).
is it possible to surface this to user? I'm noticing stuck behaviour and i'm not sure if its actually working or rate limited or stuck due to some connectivity issue. why does it need to say thinking all the time? Sometimes i've noticed its stuck on other things also, like editing, reading and in between.
I'm not seeing this particular issue anymore, at least not for the past maybe week or so
I am having his issue right now, not able to return a single prompt, really frustrating
Oh, I can assure you, it is. I have experienced it many times recently including 3x today. Extremely frustrating and wild this is not fixed (I am on latest Codex).
For the recent "not sure if it is working, rate-limited, or stuck" comments, I put together a small local-only PowerShell diagnostic that may make future reports easier to classify:
https://gist.github.com/ai-hustle-bro/6db680e4fd932edc580790ed1eba69d6
It scans local Codex session JSONL and log files for two timing-only signals:
model_client.stream_responses_*spans wheretime.idleis highIt does not upload anything, and by default it does not print prompts, responses, or exact local file paths. It replaces paths with short SHA-256 hashes unless
-IncludeFileNamesis explicitly passed.This does not claim a root cause or fix. It is just a privacy-preserving report generator so a "Thinking"/"Working" stall can be described as, for example, "first output gap was 984s on gpt-5.5/xhigh" or "stream idle span was 305s on responses_http".
I asked codex to convert this to be able run via python.
i dont know whats happening, but whenever i face the stuck issue in codex now, i run this script.
This script runs and then automatically the agent is able to continue.
i'll share some output:
Also note, whenever i faced this, i used to stop the session. sometimes sending some newer messges worked. sometimes it didnt work.
PS: I'm on mac. just noticed this is related to windows. sorry if this is the wrong place.
I added a Python version to the same diagnostic gist:
https://gist.github.com/ai-hustle-bro/6db680e4fd932edc580790ed1eba69d6
New file:
codex_first_output_gap_report.pyUsage:
It keeps the same privacy defaults as the PowerShell version: no prompt text,
no response text, and local file paths are replaced by short hashes unless
--include-file-namesis explicitly passed.One caveat on the "running this makes the stuck agent continue" observation:
the script is read-only, so I would not treat it as a fix. If it correlates
reliably, the interesting data point is probably the timestamp: whether the
agent continues exactly when the stuck stream times out, when a log span closes,
or when another local process reads the files. The report output plus the Codex
app/CLI version should still be useful evidence.
Wanted to give an update:
Faced this only once since the last message. That time running the script as per my prev msg didnt fix.
Haven't faced it since. (been over a week)
faced this today @ai-hustle-bro :
This is the new python script output u shared.
The conversation was started an hour back and it concluded correctly.
later after some 30+ min i sent a message and it was stuck for a while.
i started a new conv and typed "hi". it worked. the other conversation remained stuck.
after sometime, agent started responding.
at all times, it showed "thinking"
I’m seeing a similar stall, but the duration was at least over 1 hour.
Environment/context:
Observed behavior:
After Codex made file changes, the session stayed stuck without visible progress for more than an hour. Using “Resume goal” did not recover the run. The only workaround that helped was to interrupt the entire session first, then use “Resume goal” afterward.
From the user side, this looks similar to the long thinking / pre-output stall described in this issue, except in my case it happened in the VS Code extension with Goal mode enabled rather than the Desktop app.