Repository navigation
[Windows] One missing chunked-message acknowledgement blocks every later host→renderer message (no timeout): sends spin forever, finished turns stay on "Thinking" #50203
Description
What version of the Codex App are you using (From “About Codex” dialog)?
Seen on 26.928.40906 (MSIX OpenAI.Codex 26.928.4866.0, app-server 0.159.2). The code path described below is unchanged in 26.930.21537 (MSIX 26.930.2377.0, app-server 0.159.0-alpha.12.1).
What subscription do you have?
ChatGPT Pro (5x)
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64
What issue are you seeing?
The primary window stops receiving every message from the host. Nothing reaches it: no replies, no notifications, no turn progress. The app-server and the main process keep working the whole time:
- A message sent from the composer spins forever. The send first waits for
thread/queue/list, and that reply never arrives, soturn/startis never sent. Clicking Send again does the same. - A turn that is running, or has already finished on the server, stays on "Thinking" in the window. The rollout file shows the turn completing (
task_complete) several minutes later. - Follow-ups typed while that turn is running are neither queued nor sent.
- There is no error in the UI. The desktop log keeps logging
response_routed ... targetDestroyed=falsefor every request the window makes.
The state does not recover by itself. Reloading the window fixes it (in one case it took two reloads).
Measurements from one occurrence (26.928.40906, right after a cold start):
- Replies stopped reaching the window within the first minute after launch and did not resume. In the first 4.5 minutes after launch the desktop log recorded 266
response_routed ... targetDestroyed=falselines for this window. - For 12 s, a
messagelistener in the window recorded zero events. - I sent a harmless read (
thread/loaded/list) throughelectronBridge.sendMessageFromView. The desktop log shows it routed (response_routed ... requestId=probe-… targetDestroyed=false), but the window never received the reply. - After a reload, a listener installed at document start showed a chunked transfer (
codex-host-chunked-message-v1, start + 13 chunks + end) arriving in 2.5 s. All the queued messages (mcp-response,mcp-notification,shared-object-updated, …) arrived immediately after itsend, and the window worked normally again.
Likely cause (from the shipped main bundle)
The chunked sender in the main process (the class with send, sendCritical, acknowledge, drain, sendNextPart):
- Messages larger than
inlineThresholdBytes(4 MiB) are sent as parts of 2 MiB batches. - The next part is sent only from
acknowledge(target, transferId, sequence). That happens when the renderer callselectronBridge.acknowledgeChunkedMessage(transferId, sequence)after its windowmessagehandler processed the part. - While
target.transfer != null,drain()returns early. Every other message for that webContents, including small ones, is pushed totarget.messagesand waits behind the transfer. - There is no timer on the acknowledgement.
retryDelayMsonly applies whendeliverthrows.
So if a single acknowledgement never reaches the main process, that window receives nothing until it reloads. A reload resets the transfer (handleLoading re-queues it, handleLoaded drains again), which matches what we see.
In the occurrence above I could not see which part went unacknowledged: the window started losing messages before I could record its message events. Everything else fits: the host routes, the window receives nothing, a reload starts with a large chunked transfer, and then everything flows. Right after startup is also when a message can arrive before the renderer's handlers exist. The same window also misses the one-time codex-app-server-initialized message at startup (#49718).
I checked one thing against the running app: an acknowledgement for a transferId/sequence the host is not waiting for is ignored, and the window keeps working. So re-acknowledging the last part the window saw is a safe client-side workaround.
What steps can reproduce the bug?
Intermittent, mostly right after a cold start, with large threads open (rollouts of tens of MB with images make the large initial messages likely):
- Start the Codex app with a few large local threads.
- Open a large thread and send a message, or wait for a running turn.
- Sometimes the composer spins and the thread shows no progress. The desktop log keeps logging
response_routedfor that window, and the window receives nomessageevents. - Reload the window: everything resumes.
What is the expected behavior?
A lost or late acknowledgement should not stop all later messages to the window. For example:
- Put a time limit on the acknowledgement, then re-send the current part or restart the transfer.
- Don't hold small messages behind an incomplete chunked transfer.
- Have the renderer report "I have no transfer in progress" on mount, so the host can restart a transfer the renderer never saw.
Requests from the renderer should also not wait without a time limit (timeoutMs 0). At least the composer should surface an error instead of spinning.
Additional information
Possibly the same root cause as #45371 ("app-server responses lost during the ~20 s renderer mount; composer spins forever") and #47795 ("early vscode://codex/* fetch responses are silently lost at startup"). Both describe replies the host produced that never reach the window, with no error.
I wrote a local workaround that re-acknowledges a stalled part and reloads the window when routed replies stop arriving: https://github.com/tomhda/codex-app-recovery (it does not modify the app). It has only been verified on my own machine, on the versions listed above. It works around the symptom; it is not a fix.
Activity
github-actions commentedon Oct 2, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
tomhda commentedon Oct 2, 2026
Not a duplicate, I think: #49062 describes the same symptom (finished replies never appear until the conversation is reopened), and this issue gives a likely cause for it. The desktop log shows every reply routed to the window, the window receives none of them, and the main process's chunked sender holds all later messages behind an unacknowledged part with no time limit. Leaving this open as the root-cause report; linked from #49062.