openai / openai/codex

[macOS Desktop 26.901.31953] retained per-thread MCP runtimes exhaust swap; ChatGPT reaches 13.6 GB and hard-freezes a 16 GB Mac

Open
#44,996 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app bug mcp performance session
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

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.

This is a Codex Desktop process-tree/lifecycle bug, not memory allocated by the user workloads. The precise final split between renderer heap, app-server state, and retained helper processes cannot be recovered because the machine required a hard reboot and no hang/heap report survived. The attribution and failure mechanism are nevertheless supported by independent system and application evidence:

  1. The macOS application-memory UI attributed approximately 13.6 GB to ChatGPT/Codex immediately before the freeze.

  2. 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.
    
  3. The pre-reboot Codex Desktop log ends abruptly at 15:17:56.969 local time with a main_thread_jank_snapshot (mainThreadJankCountSinceLastSnapshot=2). The machine booted again at 15:22:22; there is no clean shutdown record.

  4. 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.

  5. 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, and node_repl.

  6. 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.

  7. 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 user workloads do not explain the 13.6 GB attribution. The three relevant persisted JSONL files were only about 35.7, 42.1, and 40.8 MB (about 119 MB total). The largest separate workload observed after recovery, a Python data refresh matching the pre-freeze command, used only about 63–66 MB RSS and appears as its own process rather than as ChatGPT in macOS's UI.

My conclusion is high-confidence but deliberately scoped: 13.6 GB was the accumulated Codex/ChatGPT application process tree. Retained per-thread MCP/plugin runtimes are a directly reproduced root cause; concurrent multi-task event/history fan-in into the renderer is a likely amplifier. The hard reboot prevents assigning every final GB to a specific child process.

What steps can reproduce the bug?

The destructive end state was not intentionally reproduced after reboot. The underlying retention is reproducible safely:

  1. Start Codex Desktop with several local tasks available and the bundled app/plugin MCP servers enabled.
  2. Run or resume multiple tasks so each initializes its normal tool set (codex_app, codex_apps, cua_repl, openai_artifact_template_picker, and node_repl).
  3. Let the tasks perform ordinary long-running work with streamed reasoning, tool calls, and tool output.
  4. Stop the tasks and confirm they are idle.
  5. Inspect the app-server process tree. The per-thread MCP/plugin helper sets remain alive instead of being reaped.
  6. Resume or create more tasks. Additional per-thread sets start while the old sets remain.
  7. 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?
  • Stopping, completing, idling, unsubscribing, closing, or archiving a task must shut down its per-thread MCP/plugin subprocess tree.
  • 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

This incident is likely another manifestation of the lifecycle defect in #30408. It is also related to #32942 (restored-task MCP fan-out and renderer failure) and #22991 (large-history UI stalls). I am filing a separate incident because this occurred on the current 26.901.31953 build and adds a kernel-confirmed, system-wide swap exhaustion failure on a 16 GiB Mac, plus a controlled post-reboot reproduction showing that helper sets remain after their tasks are stopped.

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the retained per-thread helper sets and inspecting the app-server process tree after tasks become idle. Compare the lifecycle defect with issues #30408, #32942, and #22991, using the supplied logs and process snapshots. Done means task-owned MCP/plugin subprocesses are reaped or safely shared, helper and renderer memory remain bounded, and the Desktop app stays responsive under concurrent tasks.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, rust
Domain
desktop, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.