Repository navigation
[macOS Desktop 26.901.31953] 13.6 GB application-memory report and swap exhaustion hard-freeze a 16 GB Mac; per-thread runtimes retained #44996
Description
What version of the Codex App are you using (From “About Codex” dialog)?
Codex Desktop 26.901.31953 (build 7868), bundled codex-cli 0.153.1.
What subscription do you have?
Paid ChatGPT subscription (exact tier omitted from this public report).
What platform is your computer?
Darwin 25.4.0 arm64 arm (macOS 26.4.1 build 25E253, Apple silicon, 16 GiB physical RAM).
What issue are you seeing?
Codex Desktop grew to approximately 13.6 GB in macOS's application-memory UI and exhausted swap while three ordinary local tasks were running concurrently. The entire Mac became unresponsive, including the Force Quit UI, and required a hard reboot after approximately ten minutes.
Investigation correction, October 16: the kernel-confirmed swap exhaustion and user-observed 13.6 GB attribution stand. The post-reboot measurements establish helper retention after Stop/idle, but do not establish failed archive/removal teardown or prove that MCP helpers caused the full pre-reboot footprint. See the lifecycle clarifications in the comments and the separately captured October incident, #54416.
The precise final split between renderer heap, app-server state, retained helper processes and any associated workloads cannot be recovered because the machine required a hard reboot and no hang/heap report survived. The surviving system and application evidence is:
-
The macOS application-memory UI attributed approximately 13.6 GB to ChatGPT/Codex immediately before the freeze.
-
The unified system log identifies the old ChatGPT PID and records:
2026-09-12 15:16:20.256 kernel: memorystatus: doing pcontrol on ChatGPT [PID] 2026-09-12 15:16:20.256 kernel: memorystatus: suspending ChatGPT [PID] due to swap exhaustion 2026-09-12 15:18:28.474 WindowServer: pid [PID] failed to act on a ping it dequeued before timing out. -
The pre-reboot Codex Desktop log ends abruptly at
15:17:56.969local time with amain_thread_jank_snapshot(mainThreadJankCountSinceLastSnapshot=2). The machine booted again at15:22:22; there is no clean shutdown record. -
In the final seconds before the log stopped, reasoning/item events from all three active top-level tasks were interleaved through the same
rendererWebContentsId=1. -
During that Desktop lifetime, the log recorded 724 MCP startup-status events covering 49 distinct thread IDs and 183 distinct thread/server pairs. A normal full thread runtime included
codex_app,codex_apps,cua_repl,openai_artifact_template_picker, andnode_repl. -
After reboot, I reproduced the lifecycle retention without driving the machine back to OOM: after the three recovered tasks were explicitly stopped and confirmed idle, their per-thread helper sets remained children of the long-lived app-server. Four top-level sets were present (the three idle tasks plus the current diagnostic task), including four copies each of the app-tools server, CUA launcher, artifact-template picker, and top-level Node REPL, plus nested Node REPL children. They did not exit when their owning tasks became idle.
-
In that fresh post-reboot snapshot, the ChatGPT/Codex tree already used approximately 3.25 GB RSS. Four renderer processes used approximately 1.30 GB combined; the primary renderer alone was approximately 0.84–0.88 GB and grew while diagnostic output streamed. The app-server used approximately 0.31 GB. The retained per-thread helper baseline accounted for hundreds of additional MB before meaningful work resumed.
The three relevant persisted JSONL files were about 35.7, 42.1, and 40.8 MB (about 119 MB total). A Python data refresh matching the pre-freeze command used about 63–66 MB RSS after recovery. Neither serialized file size nor a post-reboot workload sample reconstructs the pre-reboot live heap or rules out every workload contribution.
Confirmed: macOS suspended ChatGPT during swap exhaustion, the user saw about 13.6 GB attributed to it, and helper sets remained after recovered tasks were stopped. Not established: the final per-process allocation split, an exact retaining object, failed archive shutdown, or MCP helpers as the dominant cause. Multi-task state/event retention and helper lifecycle policy remain investigation leads. Stop/idle, unsubscribe, and archive/removal must be tested as different lifecycle operations.
What steps can reproduce the bug?
The destructive end state was not intentionally reproduced after reboot. The underlying retention is reproducible safely:
- Start Codex Desktop with several local tasks available and the bundled app/plugin MCP servers enabled.
- Run or resume multiple tasks so each initializes its normal tool set (
codex_app,codex_apps,cua_repl,openai_artifact_template_picker, andnode_repl). - Let the tasks perform ordinary long-running work with streamed reasoning, tool calls, and tool output.
- Stop the tasks and confirm they are idle.
- Inspect the app-server process tree. The per-thread MCP/plugin helper sets remain alive instead of being reaped.
- Resume or create more tasks. Additional per-thread sets start while the old sets remain.
- With multiple tasks streaming into the same Desktop renderer, observe increasing renderer RSS and main-thread jank. On the reported 16 GiB Mac, the accumulated application tree reached approximately 13.6 GB, exhausted swap, and hard-froze the OS.
What is the expected behavior?
- Completed/inactive tasks should have a documented, bounded retention policy. Stop/idle and unsubscribe need not be equivalent to archive/removal; archive/removal should reliably release resources owned exclusively by the removed task without disrupting other owners.
- Restored tasks should not eagerly create and indefinitely retain one full helper set per historical task.
- Helper count and memory should be bounded by currently attached/active tasks, with sharing or lazy startup where safe.
- Renderer state and event fan-in should remain bounded when several long-running tasks produce events concurrently.
- Codex Desktop must remain responsive and release memory before it can exhaust system swap.
Additional information
Related investigation leads are #30408 (MCP lifecycle), #32942 (restored-task MCP fan-out and renderer failure), and #22991 (large-history UI stalls). A shared root cause is not established. This report preserves a kernel-confirmed, system-wide swap-exhaustion incident on build 26.901.31953 and the separate post-reboot Stop/idle retention observation. #54416 contains the newer incident's directly captured process footprints and should be evaluated independently.
The persisted Codex state is large overall (544 active rollout files totaling about 10.61 GB), which may increase restore/index/hydration pressure, but the three active incident sessions were only about 119 MB combined. Therefore persisted file size alone cannot account for the observed 13.6 GB application footprint.
Task names, prompts, thread IDs, local paths, and raw logs are intentionally omitted. Sanitized process snapshots and timestamped log excerpts can be provided if useful.
Activity
github-actions commentedon Sep 12, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
alaemiryoung commentedon Sep 12, 2026
I reviewed all five suggested issues before deciding whether to close this report:
thread/start/ ambient-prewarm leaks, with a new hidden helper pool approximately every five minutes.io_uring/memlock budget.They are in the same lifecycle family, but none is an exact match for this incident's trigger and failure evidence: three visible user tasks were actively running on macOS, their helper sets remained after the tasks were explicitly stopped, the macOS kernel recorded
suspending ChatGPT ... due to swap exhaustion, and the machine hard-froze with ChatGPT/Codex at approximately 13.6 GB.The closest underlying lifecycle report is #30408, and the closest macOS restored-task/renderer report is #32942; both were already linked in the original body. I am keeping this issue open for now because it supplies a current-build, kernel-confirmed system-wide failure on a 16 GiB Mac. If maintainers prefer consolidation, I can move the unique sanitized timeline and process evidence to the canonical issue.
84dnnvbdvp-debug commentedon Sep 12, 2026
Current public app-server code gives one useful lifecycle discriminator for the “stopped but helpers remain” observation.
thread/unsubscribeonly removes the calling connection fromThreadStateManager; it does not shut down or remove the thread runtime. By contrast, the archive/removal path callsremove_thread_for_client(), then explicitly waits onthread.shutdown_and_wait()before final teardown.ThreadManager::remove_thread()also notes that removing the map entry does not guarantee destruction because otherArc<CodexThread>references may still exist.The private Desktop mapping of the UI Stop action is not visible in this public source, so I would separate two cases in the next reproduction:
thread/unsubscribe, retained per-thread MCP helpers point to a lifecycle-policy/UI-contract issue rather than a failed archive shutdown.A regression should distinguish
unsubscribe -> runtime may remain loadedfromarchive/removal -> thread runtime and thread-owned helper subtree must be gone, rather than using “task is idle/stopped” as one lifecycle state. That should narrow whether the fix belongs in Desktop’s stop-to-lifecycle mapping or in core/app-server cleanup itself.0xdevalias commentedon Sep 22, 2026
Corroborating current macOS evidence from Desktop 26.903.71938 / Codex 0.153.4: retained loaded sessions mapped one-for-one to
node_replplus per-task Computer History clients, and a focus-triggered plugin reconciliation restarted MCP fleets across the retained set in a tight burst. Uninstalling an unused curated Security plugin through first-class app control caused all 50 already-running Security MCP children to exit naturally, reclaiming about 2 GiB without killing individual children.For session cleanup, one completed non-window task did fully unload about 60 s after
thread/unsubscribewhen the caller was apparently the final owner. Four other completed ordinary tasks and one completed automation returnedunsubscribedbut stayed loaded beyond 60 s, demonstrating a hidden subscriber/activity owner. Thus unsubscribe-and-wait is a validated but conditional workaround, not a general fix: protect UI/history/agent/approval owners, unsubscribe, wait >=60 s, and verify the exact bundle exits. Subscriber diagnostics and an explicit unload operation are still needed.alaemiryoung commentedon Oct 15, 2026
October 16 follow-up: another system-wide swap-exhaustion incident occurred on Desktop
26.1007.71326(build20398). I filed the independently captured evidence as #54416 because the dominant memory breakdown is different.This time Apple's WindowServer watchdog stackshot preserved main-process footprint 3270.41 MiB, all renderer footprints 5679.47 MiB (largest renderer 4551.54 MiB), bundled app-server 406.56 MiB, and Node/Node REPL helpers 754.01 MiB combined. A separately identified subtitle task launched one full-file MLX Whisper worker, adding 5094.32 MiB shortly before the kernel failed to create another swapfile, suspended ChatGPT and unrelated applications, and WindowServer timed out.
This evidence does not support attributing the October event primarily to retained MCP helpers. It instead motivates separate investigation of large desktop conversation/renderer state and the agent's resource-unaware full-audio ML workload selection. The new report includes sanitized timing, task attribution, shipped-code inactivity-policy observations, and explicit limits on what can be proven without a surviving heap profile.
Also acknowledging the lifecycle clarification above: a stopped/idle task retaining helpers is not by itself proof of failed archive/removal teardown. The original September observation establishes retention after Stop, but does not establish that an archive shutdown RPC occurred and failed. Please interpret the original root-cause wording with that limitation; I have not retrospectively proved the full 13.6 GB September allocation split.
[-][macOS Desktop 26.901.31953] retained per-thread MCP runtimes exhaust swap; ChatGPT reaches 13.6 GB and hard-freezes a 16 GB Mac[/-][+][macOS Desktop 26.901.31953] 13.6 GB application-memory report and swap exhaustion hard-freeze a 16 GB Mac; per-thread runtimes retained[/+]alaemiryoung commentedon Oct 15, 2026
Thank you @84dnnvbdvp-debug and @0xdevalias. I have now corrected the original issue title/body, not just the follow-up comments, to distinguish Stop/idle retention from archive/removal teardown and to retract MCP helpers as a proven dominant cause of the September footprint.
The newer shipped Desktop
26.1007.71326inactivity path uses a three-hour TTL and a count threshold of ten eligible inactive owner conversations, excludes active/followed/keep-loaded contexts, and clears turn data only when further eligibility conditions hold. The retained application logs contain sixteen successful inactive unsubscribe events. This is consistent with ownership/eligibility affecting reclamation; it does not reproduce or disprove your earlier final-owner observations, or demonstrate failed archive cleanup.The October stackshot in #54416 separately identifies main/renderer memory as the dominant desktop footprint and a 5 GiB agent-launched ML workload as an additional contributor. Any future lifecycle reproduction should record the exact RPC, all remaining owners/subscribers, task-specific helper identity, and measured teardown result. I have not archived a user's active task to manufacture that test.