Codex Desktop meta-bug: unbounded session/turn state causes freezes, context bloat, and lost active-turn control
What version of the Codex App are you using (From “About Codex” dialog)?
26.527.60818
What subscription do you have?
pro
What platform is your computer?
Microsoft Windows NT 10.0.19045.0
What issue are you seeing?
Codex Desktop meta-bug: unbounded session/turn state causes freezes, context bloat, and lost active-turn control
Suggested labels
bug, app, session, context, tool-calls, performance, app-server
Summary
Several open Codex issues appear to be different symptoms of the same larger reliability problem:
Codex Desktop allows local session/turn state to become unbounded, then places that state on hot UI, resume, context assembly, IPC, and active-turn ownership paths. Once a thread is long-running, tool-heavy, image-heavy, repeatedly compacted, or has experienced renderer/restart/interrupt recovery, the app can freeze, become extremely slow, overfill context, lose trace/progress visibility, fail Stop/cancel, or continue backend work while the UI appears stuck in Thinking.
I do not think every linked issue is the same single code bug. The clearer framing is one parent/meta bug with several fix surfaces:
- unbounded persisted rollout/session records;
- full-history hydration into app-server/client/renderer state;
- context replay/compaction retaining large tool or image payloads;
- renderer/app-server turn ownership and trace-stream rehydration losing authority;
- insufficient diagnostics, because very different waits all collapse into
Thinking,Working, orReconnecting.
Evidence from related open reports
1. Large local rollout/history hydration makes Desktop slow, frozen, or unrecoverable
- #18693 reports a verified A/B profile test where a copied profile is smooth until only a few giant local histories are restored. Largest anonymized rollouts were about
455 MiB,507 MiB,561 MiB,584 MiB, and1867 MiB; operations such as resume/read/unsubscribe could take tens of seconds, with worst cases around82s. - #20269 reports a long-running Windows Desktop task producing a
718.6 MBrollout JSONL with3,305lines. After force quit, every launch auto-resumed the oversized session and froze. Renderer CPU was around140%of one core and working-set memory grew by about1.177 GBin10s. - #22991 reports multiple long-running session files around
500 MBor larger. The strongest freeze occurred not merely when opening a large conversation, but when sending a new prompt in an already-open large thread. - #11984 is the long-running umbrella report for Desktop UI lag during long sessions. Later comments tie the problem to full history hydration, renderer CPU/RSS, and large IPC/app-server payloads rather than only DOM rendering.
- #21299 reports Windows long-thread message submit lag: sending a new message in a long thread makes the app unresponsive for about
5s, and pruning old local JSONL session files is reported as a workaround.
2. Hard size limits and inline payloads expose the same design failure
- #22004 reports a reproducible Electron main-process crash,
RangeError: Invalid string length, when loading sessions whose rollout JSONL exceeds V8's max string length. Reported sizes include506.8 MB,786.7 MB,963.5 MB,1050 MB, and1601 MB. Related comments report an825 MBrollout producing a dropped405 MBIPC payload, and a macOS1.37 GBrollout where app-server grew to6-8 GBRSS. - #24676 shows that the problem can occur below the hard
512 MBcrash threshold. A182.8 MBimage-heavy rollout had41,361lines, a max JSONL line of6,850,815chars, and many inlineimage_url/payload.imagesrecords. A newer repro was only102.44 MB, but almost the whole file wasdata:imagepayloads; a compacted record alone was24.207 MBwith16image references. - #22091 reports Desktop context growth from retained tool outputs: a fresh session reached
137,293 / 258,400tokens after a small number of visible interactions, and an earlier diagnostic reached234,757 / 258,400, then re-inflated after compaction. Several retained tool outputs were around37K-40Kcharacters each.
3. Context compaction/replay can amplify the same state bloat
- #25009 reports Desktop becoming slow or stuck after
context_compactedevents and approval transcript injection. The report found repeatedapproval assessment/TRANSCRIPT DELTAblocks containing prior tool calls, tool outputs, retry reasons, and planned actions. - #24095 tracks Windows memory spikes and freezes after repeated context compactions in a single long-running session, distinguishing this from one-time renderer regressions or image-only rollouts.
- #19842 reports Codex CLI running out of context instead of compacting/resuming a long tool-heavy thread. One tool output had an original token count of
815,104; the final token-count event reached258,400 / 258,400. - #19585 is nominally about usage depletion, but the useful overlap is the "compaction tax": failed/slow compaction and repeated reconstruction consume additional usage and make long-session failure more expensive.
4. Active turn ownership and renderer/session state can desynchronize
- #24287 reports the dangerous control-plane symptom: prompt accepted, UI stuck in
Thinking, Stop fails or is misleading, progress traces disappear, and backend usage can continue decreasing while no activity is visible. It also reports multi-window rehydration making already-visible traces disappear and state disagreements between the goal bar, prompt box, and chat/trace area. - #24434 reports a post-tool continuation stall:
pwdandrg --filesreturned successfully almost instantly, then no assistant message, no new tool call, and no task completion occurred for about6m59suntil manual interrupt. - #24263 gives concrete renderer rehydration evidence. After a renderer reload, logs showed placeholder latest-turn rebinding, completed turns marked
markedStreaming=true,Received turn/started for unknown conversation, and5,466Item not found in turn stateerrors in one Desktop log. - #23644 reports composer submit timing out after stale conversation state accumulated over several days. Local app-state snapshots included
pending_request_count=20,thread_count_active=15,thread_count_streaming_owner=6,thread_count_streaming_without_active_runtime=13,item_count_total_loaded=22550, and about201 MBof estimated delta bytes. Restart cleared the issue. - #23035 reports an orphan
task_startedwithouttask_completepoisoning reopen/resume. The rollout parsed cleanly, but balancing the orphan turn with a synthetic completion made the lifecycle valid again. This suggests interrupted/failed turns need durable terminal state or tolerant resume logic. - #21360 reports multiple turn lifecycle stall modes:
task_startedwithouttask_complete, tool outputs returned without assistant continuation, and long non-image sessions with multiple compactions and unfinished turns.
5. Transport/first-output stalls are adjacent and currently indistinguishable in the UI
Some reports may not share the same local-history root cause, but they matter because the UI collapses them into the same stuck state and recovery paths can interact with renderer/session state:
- #24260 reports a
gpt-5.5xhigh turn accepted immediately, then30m38sbefore the first persisted reasoning item. Later comments includeresponses_httpidle spans of hundreds of seconds and a packet-capture case where a reused connection was reset but recovery waited for the300sstream idle timeout. - #24414 reports the VS Code extension staying on
Thinkingfor minutes even for simple prompts. - #24419 reports CLI
Workinghangs and reconnect retries; interrupting and resubmitting the same prompt can run normally.
These may require separate transport/request watchdog fixes, but the Desktop issue should still distinguish them from renderer detachment, post-tool continuation stalls, and full-history hydration.
Suspected root cause family
The common design problem seems to be that "thread state" is doing too many jobs at once:
- durable audit log;
- UI transcript;
- context replay source;
- app-server resume payload;
- renderer live state;
- trace/progress stream state;
- tool output/image artifact store;
- recovery source after restart or renderer reload.
When those roles are all served by unbounded JSONL and large in-memory turn arrays, one oversized or inconsistent thread can poison many surfaces.
Requested fixes / invariants
Bound persisted session records
- Cap persisted
function_call_output, custom tool output,event_msgpayloads, andInputText/image fields before they enter rollout JSONL. - Do not persist raw
data:image/ base64 image payloads in normal rollout records orcompacted.payload.replacement_history; use file/blob references, hashes, or placeholders. - Avoid duplicating the same image/tool payload across both
response_itemandevent_msg. - Add rollout size warnings and automatic safe repair/export paths.
Make thread loading lazy and paged
thread/read,thread/resume,thread/turns/list, stream-state snapshots, and sidebar state should have hard byte/count caps.- Opening a thread should return metadata and a recent bounded tail, for example the most recent 100-200 messages or a small byte cap.
- Older turns, heavy tool outputs, and images should load only on scroll/expand.
- Transcript rendering should be virtualized, but virtualization alone is insufficient if full history is still hydrated into renderer/app-server state.
Separate context assembly from durable transcript history
- Context compaction should summarize or reference old heavy content instead of replaying raw tool outputs/images.
- Approval transcript or retry transcript injection should be bounded and deduplicated.
- Context/token accounting should expose whether growth came from visible user text, hidden tool output, compaction replacement history, approval transcript injection, or old transcript replay.
Make active-turn ownership durable and recoverable
- Persist a turn record and its originating thread before streaming begins.
- Persist accepted user prompts before upstream/network submission.
- On renderer reload/restart, reattach by durable turn id and event cursor, not just in-memory renderer state.
- Stop/cancel should resolve to an explicit state: cancelled, still running remotely, already completed, failed to cancel, or unknown/detached.
- If backend active turns exist without renderer ownership, show a recovery banner and reattach option.
Make resume/reconciliation authoritative
- A terminal backend turn must not rehydrate as
markedStreaming=true. - If a renderer receives item deltas for an unknown conversation, it should buffer briefly and force a thread/turn re-read instead of dropping state and spamming
Item not found in turn state. - On resume, reconcile the full item id set for the active/recent turn before applying live deltas.
- Orphan
task_startedturns should be repaired as interrupted/failed during resume rather than crashing LocalConversationPage.
Improve diagnostics
- Add phase-specific timing/log events for: request accepted, upstream request sent, response headers received, first byte, first Responses event, first assistant/reasoning/tool item, tool result returned, post-tool continuation requested, context compaction started/completed, renderer attached/detached, and Stop/cancel result.
- Keep performance traces locally if upload fails (#24262).
- Preserve enough local diagnostics to tell whether a stuck turn is model/backend stall, transport retry, context compaction, app-server hydration, renderer detachment, or post-tool continuation loss.
Related issues
Large history / full hydration:
- #11984
- #18693
- #20269
- #21299
- #22991
Hard size limits / image or tool payloads:
- #22004
- #24676
- #22091
Context compaction / context replay / usage amplification:
- #19842
- #19585
- #24095
- #25009
Turn lifecycle / UI ownership / trace and Stop desync:
- #21360
- #23035
- #23644
- #24263
- #24287
- #24434
Adjacent transport / first-output stall reports that should be distinguished in diagnostics:
- #24260
- #24414
- #24419
Potentially adjacent Desktop lifecycle reports:
- #22655
- #25094
- #21076
Why this should be tracked as a meta issue
Individual reports often look like separate bugs because the immediate symptom differs: slow thread switching, V8 string crash, image-heavy freeze, compaction memory spike, stuck Thinking, invisible active turn, failed Stop, composer timeout, missing tool traces, or CLI/extension first-output stalls.
But the recurring evidence points to one architectural boundary that needs a coordinated fix: Codex should treat durable history, model context, renderer transcript, live turn stream, and recovery state as separate bounded contracts. Until those contracts are bounded and authoritative, fixes to only one surface, such as rendering virtualization or a single timeout tweak, are likely to leave other variants open.
What steps can reproduce the bug?
User-visible failure modes
- Desktop becomes slow or unresponsive when opening a long thread, switching threads, sending a new prompt in an old thread, or after repeated context compactions.
- The app can become unrecoverable on launch if the most recent session auto-resumes an oversized rollout.
- A short follow-up in an old session can freeze the UI even though a fresh session still works.
- Tool outputs can return successfully, but the assistant continuation never resumes.
- A prompt can be accepted and backend work can continue, while the Desktop UI stays stuck in
Thinkingand no progress traces appear. - Stop/cancel can become unavailable, misleading, or ineffective because the UI has lost the active turn reference.
- After restart or renderer reload, prompts/traces/tool calls can be missing, stale, or only partially recovered.
- The same root state bloat can also drive fast context growth and usage drain through retained tool output, compaction history, and replayed approval/diagnostic transcripts.
What is the expected behavior?
Expected behavior
- Opening or switching to a thread should load metadata plus a bounded recent tail, not the entire transcript/tool/image history.
- Sending a short prompt in an old thread should not synchronously parse, render, serialize, or replay hundreds of MB of session data.
- Context compaction should reduce active prompt pressure and should not retain raw large tool outputs, image data, or repeated transcript-injection blocks.
- Rollout JSONL should not store raw image bytes or unbounded tool output inline when references, caps, summaries, or external artifacts would work.
- If one thread is too large or malformed, Desktop should fail that thread safely while leaving the rest of the app usable.
- If a prompt is accepted, the originating thread should durably show the user prompt, trace/progress stream, and Stop/cancel state.
- If the renderer loses ownership of an active backend turn, it should show an explicit recovery/reattach state rather than generic
Thinking. - Terminal backend states should be authoritative: completed, failed, interrupted, or cancelled turns should not rehydrate as streaming.
- Tool-returned, waiting-for-first-output, reconnecting, context-compacting, renderer-detached, and post-tool-continuation-stalled states should be distinguishable in UI and logs.
Additional information
_No response_
8 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
I can add another Windows Desktop datapoint that seems to fit this meta-bug.
In a long-lived Windows-native Codex Desktop workspace with many visible project threads, large transcripts, frequent cross-thread dispatches, context compaction events, interrupted turns, and recurring automations, individual threads can remain listable/readable while new turns fail to start or settings updates fail with errors such as:
failed to update thread settings: internal error; agent loop died unexpectedly
failed to start turn: internal error; agent loop died unexpectedly
Error submitting message
The important distinction is that fresh/empty threads can still accept simple messages, and restarting Codex Desktop / Codex++ often temporarily restores the same affected visible thread. So this does not look like a global account/network failure or a project-specific runtime failure. It looks more like stale or inconsistent thread/conversation/app-server state after long-lived multi-thread usage.
Local scale indicators from the affected workspace:
about 144 total thread records
about 120 project thread records
largest orchestration transcript around 532 MB
operations/patrol transcript around 173 MB
diagnostic history around 701 MB
repeated context compaction / interrupted / markedStreaming=true style evidence in local logs
Related surface also overlaps with #23971, but our trigger is not only subagent close; it is broader Windows Desktop long-lived visible-thread dispatch/start-turn degradation.
A useful product-level fix would be to expose a clearer per-thread state, for example: readable/listable but not routable, approval pending, compaction pending, stale runtime, or agent-loop failed. Right now those states can collapse into the same practical outcome: the thread looks present but cannot be safely used for automation or dispatch.
Adding a Windows Desktop data point that seems to fit this meta-bug, especially the distinction between local runtime stalls and degraded thread/session state.
In my case, two problems initially looked like the same "Codex is stuck" symptom, but they turned out to be different layers:
Documents/New projectpath was genuinely I/O-bound. Apnpm installhad produced a partially builtnode_moduleswith about90,910files /2.8 GB, and the project also had.worktreesaround250,160files /6.23 GBplus.gitaround2.44 GB. Moving/cloning the active repo to a non-syncedF:\openclaw\repos\...path made the dependency install finish in about17sand Vite become ready in about2s.shell,pnpm,gh, or similar subprocess, local CPU/RAM pressure was low, and the thread was already near the effective context window at about232k / 258ktokens. It had accumulated large prior diagnostic/tool output (doctor --fix,rg, gateway checks, etc.). That thread remained unsafe to continue even after the workspace I/O issue was fixed, so I abandoned it and continued from a short-context thread.The useful distinction for this issue is: Desktop should not make these both look like generic
Thinking/stuck states. It would help if the app could expose whether the current stall is:The product-level recovery also needs to be different. Moving the repo out of OneDrive fixes the I/O stall, but it does not rescue a degraded long-context thread. For that second case, Codex needs a safe fork/handoff/degraded-session path rather than encouraging the user to keep prompting the old thread.
I filed the narrower diagnostic-boundary issue as #28345, so this comment can stay focused on how the datapoint fits the broader session/context meta-bug.
Adding a macOS data point with a concrete IPC hard-limit failure from an oversized local rollout.
Environment
26.707.41301(build5103)150.0.7871.1150.144.0-alpha.4Local state before mitigation
The thread list itself remained fast (about 276 ms). Reading recent/light threads took about 165-393 ms. The 574 MB and 902 MB histories took about 1.26 s and 1.95 s for a bounded recent read.
However, reading the approximately 350 MB history failed after about 2.8 seconds with a concrete IPC frame error:
code-mode delegate response exceeds the IPC frame limit: code-mode IPC frame length 81989668 exceeds 67108864 bytesThis occurred even when the caller requested a bounded recent read and set output inclusion off. The returned payload path still attempted to construct approximately 82 MB for a protocol with a 64 MB single-frame limit.
Mitigation result
Moving old oversized rollouts out of the hot scan path reduced the active Codex directory from about 5.4 GB to about 2.0 GB and improved general responsiveness. The histories were preserved in a verified compressed cold backup. This is an effective local workaround, but users should not need to manually manage internal JSONL files to keep Desktop usable.
Requested invariants
I have omitted local paths, thread IDs, raw conversation content, account data, and credentials.
Adding a Windows Desktop datapoint with a deterministic failure on one oversized, long-lived thread.
Environment
26.707.3748.0Local evidence
455.67 MiBwith43,086JSONL records.task_complete; the thread remains present and listable.100%marker while the in-flight turn continued to its terminal event.Reproduction
continue working.Error submitting messageand/or a redError creating tasktoast.failed to start turn: internal error; agent loop died unexpectedlyfailed to update thread settings: internal error; agent loop died unexpectedlyThe original rollout remains parseable and its prior terminal event is intact. No active local subprocess explains the failure.
Expected behavior
agent loop died unexpectedly.This appears consistent with the meta-bug's unbounded history plus thread-routing failure family, while also exposing a misleading usage-limit-to-internal-error mapping.
Additional Windows evidence from July 11, 2026. This variant presents as repeated full Desktop process exits/relaunches, not only an in-place renderer reload.
Environment
26200, x64OpenAI.Codex_26.707.3748.0_x64__2p2nqsd0c76g0codex-cli 0.144.1Observed process lifecycle
The Desktop logs show several sessions ending abruptly without the normal:
A new Desktop process was then launched shortly afterward:
The third sequence ended immediately after stale-conversation events and browser-sidebar teardown:
Error volume before exits
Main-process/Desktop logs for the affected runs contained:
Across these sessions, the dominant error categories were:
One affected session started emitting
Received turn/started for unknown conversationonly seconds after startup while other threads were actively streaming. Subsequent events for that conversation continued for the life of the process.Negative evidence
This makes system memory pressure and a conventional WER-captured native crash unlikely.
Assessment
This appears consistent with the active-turn/renderer state desynchronization family tracked here and in #24263, but this instance escalates into repeated full Desktop process termination/relaunch. The strongest trigger correlation is multiple concurrently streaming threads plus browser/sidebar lifecycle activity. Exact reproduction is still timing-sensitive.
Useful fixes/diagnostics would include:
Additional macOS reproduction from Codex Desktop release
26.707.72221/ bundled CLI0.144.2:Fresh image thread stalled before first output
019f5fe0-c206-7100-89a8-05c9dc96e3e9.turn/startin ~29 ms.Received turn/started for unknown conversationwith conversation ID
019f5fe0-c309-7851-a255-c58d8a12d928, which did not match the actual thread ID.turn/start, there was no persisted reasoning item, assistant message, tool call, completion event, or explicit error.active / inProgressuntil the turn was manually interrupted roughly 3 minutes later.The
unknown conversationevent is correlated with the stall but is not proven to be the root cause. It may indicate a thread/turn routing or renderer reattachment race. The important user-facing issue is that the app exposed only a generic active/thinking state and no recoverable phase-specific error.After restart, the image pipeline completed again but remained very slow: 130.7 seconds cold and 45.4 seconds warm for a trivial one-line response. That controlled performance reproduction is tracked in #33018.
No private image content or raw logs are included in this comment.
Adding a reproducible Windows Desktop datapoint with a same-version CLI control test.
Environment:
history_mode=legacyObserved failure:
Same-version control:
0.144.2) successfully loaded the 108 MB history and returned the requested short response.agent loop died unexpectedly.This narrows the failure to the Desktop/background agent-loop lifecycle or thread-loading/ownership path rather than the model, account quota, working directory, rollout parseability, or core direct-resume capability.
Additional signals:
task_startedwithout a matchingtask_complete, although later turns completed successfully, so stale lifecycle state may be a contributing factor.failed to refresh available models: timeout waiting for child process to exitafter the models HTTP request itself returned 200. I cannot prove this is causal.Expected behavior:
Privacy:
Related exact error family: #23971. Related long-history/direct-resume behavior: #25215 and #25430. A recent minimal report with the same message was #33206.