Repository navigation
Codex Desktop writes empty assistant messages when continuing an older resumed thread #28751
Description
What version of the Codex App are you using (From “About Codex” dialog)?
Codex Desktop on Windows. Observed in logs: - Codex package: OpenAI.Codex_26.611.8604.0_x64__2p2nqsd0c76g0 - Browser/Codex release field seen in logs: 26.611.62324 - Session metadata CLI version: 0.136.0-alpha.2
What subscription do you have?
Plus
What platform is your computer?
Windows 10 / Windows Desktop.
What issue are you seeing?
When continuing an older Codex Desktop thread, Codex appears to complete the turn, but the assistant response is saved as an empty message.
The user-facing behavior is:
- I send a message in an older thread.
- The response may briefly appear or the turn appears to complete.
- The final visible assistant message is empty / disappears.
- The thread remains usable enough to open and resume, but future assistant responses in that thread are also saved empty.
- Newer/fresh threads do not consistently show the same behavior.
The session file contains successful user messages followed by empty assistant messages:
{"timestamp":"2026-06-17T16:26:55.122Z","type":"response_item","payload":{"type":"message","role":"user","content":[{"type":"input_text","text":""}]}}
{"timestamp":"2026-06-17T16:27:28.204Z","type":"event_msg","payload":{"type":"agent_message","message":"","phase":null,"memory_citation":null}}
{"timestamp":"2026-06-17T16:27:28.213Z","type":"response_item","payload":{"type":"message","role":"assistant","content":[]}}
{"timestamp":"2026-06-17T16:27:28.232Z","type":"event_msg","payload":{"type":"task_complete","turn_id":"019ed668-3880
The important part is:
agent_message message=""
assistant content=[]
task_complete last_agent_message=null
But the same turn has token usage recorded:
"last_token_usage":{"input_tokens":3326,"cached_input_tokens":0,"output_tokens":1572,"reasoning_output_tokens":0,"total_tokens":4898}
So this does not look like a normal "model returned no output" case. It looks like generated output was lost between the model/app-server pipeline and transcript persistence/rendering.
What steps can reproduce the bug?
I do not have a minimal deterministic reproduction yet, but the observed path is:
Open an older Codex Desktop thread created several days earlier.
Let Codex resume the thread.
Send a new user message.
Codex starts and completes the turn.
The session file records an empty assistant message with content: [].
The UI shows no usable assistant response / the response disappears.
Relevant logs around resume show that the old thread loads successfully:
2026-06-17T16:04:46.504Z info [AppServerConnection] response_routed ... conversationId=019ea5d4-bd16-7332-9cdf-ad2e9b0663dc ... errorCode=null ... method=thread/read
2026-06-17T16:04:52.820Z info [AppServerConnection] response_routed ... conversationId=019ea5d4-bd16-7332-9cdf-ad2e9b0663dc ... errorCode=null ... method=thread/resume
2026-06-17T16:04:52.865Z info [electron-message-handler] maybe_resume_success conversationId=019ea5d4-bd16-7332-9cdf-ad2e9b0663dc latestTurnStatus=completed markedStreaming=true turnCount=9
A later turn starts successfully:
2026-06-17T16:26:54.975Z info [AppServerConnection] response_routed ... conversationId=019ea5d4-bd16-7332-9cdf-ad2e9b0663dc ... errorCode=null ... method=turn/start
Then the persisted transcript contains an empty assistant message and task_complete with last_agent_message=null.
In one earlier retry on the same old thread, a rollback happened before another empty response was recorded:
2026-06-17T16:04:56.425Z info [AppServerConnection] response_routed ... conversationId=019ea5d4-bd16-7332-9cdf-ad2e9b0663dc ... method=thread/rollback
What is the expected behavior?
When a resumed old thread completes a turn, the assistant response should be persisted and rendered normally.
If the response cannot be generated or persisted, Codex should show a visible error instead of writing: {"role":"assistant","content":[]}
and marking the task complete with:
"last_agent_message": null
Codex marks the turn complete, records token usage, but persists an empty assistant message:
agent_message message=""
assistant content=[]
task_complete last_agent_message=null
This makes the thread appear broken: the user sees no answer, and subsequent attempts in the same old thread can repeat the same empty-output behavior.
Additional information
Additional diagnostics
I checked for the previously reported rollout is empty / thread/read failure pattern, but this does not appear to be the same bug.
For this affected thread:
thread/read returns errorCode=null
thread/resume returns errorCode=null
turn/start returns errorCode=null
no rollout is empty error was observed for this thread
the failure is visible in the session JSONL as empty persisted assistant content
There were unrelated warnings/errors in the same Codex Desktop logs, including Git dubious ownership and Windows workspace dependency warnings, but the old thread itself resumes successfully before the empty assistant message is written.
Impact:
This is data-loss-like behavior for long-running Codex Desktop threads. Older threads can become effectively unusable because new assistant responses are completed but stored as empty messages, making it impossible to continue work from that thread.
Activity
a09472610-star commentedon Jun 17, 2026
Workaround: creating a branch/fork from the affected thread makes the conversation usable again. Continuing the original resumed thread writes empty assistant messages, but the branched thread works normally.
zmc1997 commentedon Sep 2, 2026
I am also seeing the completed-but-empty-response symptom on macOS with a newer build:
26.820.71523(build7226)0.150.0-alpha.8In the latest occurrence:
From the UI alone I cannot yet determine whether the generated response was persisted and dropped by the live projection, or whether the turn completed with empty assistant content. Either case should produce a visible synchronization/error state rather than silently presenting a successful empty turn.
This may be part of the same broader turn-lifecycle/recovery problem reported in #24287. I added the related stuck-stream behavior there: #24287 (comment)
Expected behavior:
No thread IDs, raw logs, screenshots, local paths, repository names, account details, or project content are included.
StevenVincentOne commentedon Sep 6, 2026
Same signature on
26.901.51231(Windows 11 + WSL2 Ubuntu 24.04, Windows-native agent): turns run to completion (~80–88s of billed work) but persist nothing — null assistant payload on the completion record and an empty items array on authoritative re-read.Four occurrences, two models (
gpt-5.6-sol×3,gpt-6-astra×1), so this looks host-side and model-independent. Consistent with the continuation trigger in this issue: one failing turn was a same-directory fork, another a same-task follow-up. One notable isolation: an occurrence reproduced with no worktree provisioning involved at all, so this is not a provisioning artifact.Impact beyond the lost text: the failure hides behind a success status, and reruns are expensive at frontier-reasoning cost. Current mitigation is persisting responses to files, which should not be load-bearing.
Question for triage: does the empty-write-on-continuation hypothesis cover same-task follow-ups and forks, or should those split into their own issue? Turn IDs available on request (truncated here):
01a07884-…, plus three further occurrences on 2026-09-06.StevenVincentOne commentedon Sep 7, 2026
Follow-up with app-server log evidence from one of our occurrences (same build, 26.901.51231), which strengthens the continuation hypothesis.
The empty turn's ID appears in 86 log rows, including 5 identical ERRORs spanning the turn's full ~87s lifespan, all in
run_turn.prepare_sampling_request_input:Custom tool call output is missing for call id: call_…. So every sampling-request assembly failed validation because a prior tool call's output was absent from thread state; the turn burned its duration retrying and terminated complete with nothing — matching the billed-time-with-no-payload signature.Context: this turn was a same-directory fork (resumed state), cross-checking the continuation trigger. None of the error rows contain any WSL/UNC/path content, and environment resolution logged only a benign warning. Caveat: the missing output could itself be the victim of an earlier failed write rather than the original sin — but the fatal blow lands in state assembly, not the filesystem handoff.
Full turn/thread/call IDs available on request if they help correlate.
rc314159-creator commentedon Sep 7, 2026
Additional sanitized reproduction on macOS, Codex surface in ChatGPT desktop 26.901.51231, model gpt-6-astra.
This has the completed-but-empty signature, but it is an existing-thread scheduled heartbeat that DID execute its read-only tool successfully. It is not the "automation prompt was never dispatched" case.
Observed sequence on 2026-09-07 (UTC):
The UI showed a completed duration row and feedback controls, with an empty assistant response area. This is not merely a populated response hidden by the renderer: the stored response is empty too. We do not have the raw provider stream, so we cannot distinguish model-produced emptiness from output transformation before persistence. The final sampling usage record reports output_tokens=4; this alone does not establish the cause.
Important distinction for the fix:
The automation legitimately requested quiet behavior when nothing required intervention. The turn's heartbeat response contract nevertheless required a non-empty structured result, including a quiet-status message for DONT_NOTIFY. The actual final contained neither that structured result nor ordinary text. Quiet success and an invalid empty result should be distinguishable.
Public source examined at 0df3975:
These observations describe a possible permissive completion path, NOT proof that this public revision exactly matches the installed Desktop implementation or that all None completions are bugs.
Suggested acceptance criteria:
Related: #25619 and its community null-tail recovery patch address adjacent failure paths. We have not established a stream failure or missing-tool-output validation error in this occurrence, so those should not be assumed to be this reproduction's root cause.
No screenshot, raw rollout, private prompt, thread/turn IDs, hostnames, filesystem paths, project data, or credentials are attached.
RongNianXin commentedon Oct 6, 2026
We also observed a related empty-output completion on Windows Codex Desktop.
In one captured turn:
The user-visible result was a completed turn with no usable response. Expected behavior is a visible failed/diagnostic state rather than successful completion with empty content.
The evidence is redacted and contains no task IDs, paths, credentials, or private project data. We cannot distinguish model-produced emptiness from proxy conversion or client persistence without the original provider stream and app-server trace.
Jason-Wang313 commentedon Oct 6, 2026
Additional Windows reproduction on 2026-10-06, explicitly reported by the user in Codex Desktop:
26.924.22138, build11645, production channel.answerretries.completedwitherror: null, but each turn contains only the user message and no assistant item.idle; no generation remains active.context_length_exceededor any other explicit failure.This extends the completed-but-empty symptom to the ChatGPT-conversation surface in the Windows desktop app. It is consistent with streamed output failing to persist or synchronize at finalization, although the available evidence cannot distinguish provider output loss, final-item persistence failure, or projection/rendering failure.
Expected behavior:
completed/error: nullwith no assistant item.No conversation content, IDs, screenshots, account details, local paths, or credentials are included.