[macOS App] Restored tasks fan out plugin MCP servers (~30x) and crash/reload the renderer
What version of the Codex App are you using (From “About Codex” dialog)?
26.707.71524 (build 5263)
What subscription do you have?
ChatGPT Pro
What platform is your computer?
Darwin 25.5.0 arm64 arm (macOS 26.5.1, Apple silicon, 64 GiB RAM)
What issue are you seeing?
Status correction, July 13: The Xcode-specific workaround described in the original report did not fix the issue. Another renderer crash occurred after that gate was installed. This issue remains open and reproducible, and the evidence now shows a broader restored-task plugin/MCP lifecycle defect.
Codex Desktop appears to create a full set of plugin MCP/tool helper processes for every restored task context. Those helpers accumulate under the long-lived app-server instead of being shared, started lazily, or reaped at a bounded task lifecycle. The Chromium renderer then crashes and is recreated while the outer application and app-server remain alive. The visible result is that the window blanks, disappears, and reloads as if freshly opened.
At the latest live snapshot, approximately 30 restored task contexts produced 30 copies of each helper family:
| Helper family | Copies | Combined RSS |
| --- | ---: | ---: |
| codex-security MCP | 30 | 1.81 GiB |
| Data Analytics widgets MCP | 30 | 1.35 GiB |
| Sites design-picker MCP | 30 | 1.23 GiB |
| OpenAI API-key confirmation MCP | 30 | 1.21 GiB |
| node_repl | 30 | 0.43 GiB |
The app-server used about 3.5-3.9 GiB RSS. Its 153 direct children used about 6.1 GiB, and the full Codex process tree used about 16.6 GiB.
The latest renderer crash was correlated precisely:
- Renderer Crashpad sidecar:
30d3568e-b947-4812-8565-ce474defa2fc_sidecar.json - Created:
2026-07-13 21:02:45 PDT(2026-07-14 04:02:45 UTC) - Sidecar contents:
{"osarch":"arm64","ptype":"renderer"} - Replacement renderer started at
21:02:46 PDT - React-root render requested at
21:02:48.294 PDT - Routes remounted at
21:02:48.802 PDT - Desktop and app-server PIDs did not change
- Replacement renderer grew from about 2.21 to 2.30 GiB RSS in ten seconds and continued showing high CPU use
This event was not a system-wide OOM. The machine has 64 GiB RAM, memory_pressure reported about 89% available, and swap usage was zero. The failure instead coincided with a large per-restored-task helper baseline plus an actively growing renderer and app-server.
Xcode was one leaked family, not the complete defect
The initial investigation found many restored tasks launching:
npm exec xcodebuildmcp@latest mcp
That command continued to launch despite all relevant controls resolving disabled:
[mcp_servers.xcode]
command = "xcrun"
args = ["mcpbridge"]
enabled = false
[plugins."build-ios-apps@openai-curated-remote"]
enabled = false
[plugins."build-ios-apps@openai-curated-remote".mcp_servers.xcodebuildmcp]
enabled = false
[features]
remote_plugin = false
The similarly named local marketplace plugin, build-ios-apps@openai-curated, was also removed. Verified clean starts still launched 13 and then 11 XcodeBuildMCP npm processes for restored tasks.
An initial $HOME/.local/bin/npx gate appeared to contain that exact command in short delayed samples. It was not a fix:
- A nested
codex execinherited a PATH with Homebrew before$HOME/.local/bin, bypassing the gate. - Another renderer crash occurred 21 minutes after the gate was installed.
- At that crash, only one XcodeBuildMCP launcher/worker pair remained (about 142 MiB) and no new
mcpbridgecrash coincided with the renderer failure. - The dominant load was the 30x fan-out of four other plugin MCP servers plus Node REPL.
Updating Xcode did not fix the behavior. It reproduced on Xcode 26.5 and continued after upgrading to Xcode 26.6 (17F113).
What steps can reproduce the bug?
- Use Codex Desktop with multiple tasks restorable across several workspaces and several MCP-bearing plugins available.
- Fully quit and reopen Codex so those task contexts restore.
- Inspect the app-server's child process tree and each generic Node server's working directory.
- Observe one copy per restored task of plugin servers such as Codex Security, Data Analytics widgets, Sites design picker, OpenAI API-key confirmation, and Node REPL.
- Continue ordinary work while the helper population and renderer/app-server memory grow.
- Observe the renderer blank/reload event without a clean desktop or app-server exit.
The Xcode policy-bypass variant is independently reproducible:
- Make
build-ios-apps@openai-curated-remoteavailable to restored tasks. - Disable the exact remote plugin and its
xcodebuildmcpserver, setremote_plugin = false, and remove the localbuild-ios-apps@openai-curatedcopy. - Fully quit Codex, verify new desktop/app-server PIDs after reopening, and wait several minutes.
- Run:
``text``
pgrep -af 'xcodebuildmcp@latest mcp'
Actual result: restored tasks can still launch XcodeBuildMCP even though the current plugin registry, install state, exact plugin/MCP overrides, and remote-plugin feature all resolve disabled.
What is the expected behavior?
- Restored tasks must re-resolve current plugin and MCP policy before starting helpers.
- A plugin, app, or MCP with
enabled = falsemust never launch from persisted task state. - MCP servers should start lazily only for tasks that need them.
- Identical safe servers should be shared where appropriate, or otherwise have a bounded per-task lifecycle.
- Closing, archiving, restoring, interrupting, reloading, or shutting down a task must reliably reap its subprocess tree.
- Renderer reconstruction must not replay stale tool state in a way that multiplies helpers again.
- The desktop should warn or trip a circuit breaker before process or memory growth crashes the renderer.
- Diagnostics should identify each MCP process's owning task, plugin identity/source, configuration layer, uptime, RSS, and restart count.
Additional information
Current local posture — tool catalog restored; Xcode-only containment remains
The broad plugin/app circuit breaker was rolled back because it disabled core functionality that Codex documents as part of its intended parallel, tool-rich workflow—and it did not prevent another renderer failure.
At 2026-07-13 22:08:59 PDT, Crashpad wrote another renderer sidecar, fb55976b-b3bb-486b-8e9f-a331a6ff30fd_sidecar.json, while plugins = false and apps = false were still configured. The app had already rewritten node_repl to enabled = true, and 12 Node REPL processes were present. The outer desktop and app-server remained the same long-lived processes.
At approximately 22:12 PDT, all non-Xcode tool layers were restored:
[features]
plugins = true
apps = true
remote_plugin = true
[mcp_servers.node_repl]
enabled = true
The Codex Security, Data Analytics, Sites, and OpenAI developer plugin MCP identities also resolve enabled again. The supported CLI now reports plugins, apps, remote plugins, Node REPL, and those four plugin MCPs enabled.
Only the known Xcode-specific launch paths remain contained:
- native
xcrun mcpbridge: disabled build-ios-apps@openai-curated-remote: disabled- its
xcodebuildmcpMCP: disabled - exact
npx -y xcodebuildmcp@latest mcpcommand: routed through the project allow-list from both observed PATH positions
The still-running pre-change backend began loading the restored tool set immediately. A live sample showed 3 Codex Security MCPs, 6 Data Analytics MCPs, 7 Sites MCPs, 8 OpenAI developer MCPs, 12 Node REPLs, and zero XcodeBuildMCP processes. The backend used about 4.3 GiB RSS; its 44 direct children used about 1.8 GiB. This is not a clean-start capacity measurement.
The earlier broad disablement is retained only as historical diagnostic evidence. It is not the current configuration and did not fix the renderer crash. The upstream restored-task lifecycle and policy-enforcement defect remains unresolved.
Earlier observed impact
- 25 renderer Crashpad sidecars on July 13 before the latest recurrence
- 38
mcpbridgediagnostic reports - 27 simultaneous XcodeBuildMCP npm launchers using about 1.9 GiB RSS in one snapshot
- 55 XcodeBuildMCP node workers using about 4.1 GiB RSS in an earlier snapshot
- Earlier backend peak around 4.1 GiB with hundreds of direct children and about 12.7 GiB swap in use
Related issues
- #17574 — subagents leak XcodeBuildMCP and Chrome DevTools MCP trees
- #28443 — remote curated plugins ignore per-plugin
enabled = false - #31946 — macOS Node process explosion and system-wide memory failure
- #27880 — renderer/browser crashes with stale app-server helpers
- #32339 and #32797 — flagged by the duplicate-detection action as potentially related
Project names, prompts, and private local paths are intentionally omitted. Sanitized process samples, configuration snapshots, and crash metadata can be provided if needed.
7 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Follow-up: another renderer crash proves this is broader than XcodeBuildMCP
Another renderer-only crash/reload occurred on July 13 at
21:02:45 PDT(04:02:45 UTC), 21 minutes after the initial PATH-level Xcode gate was installed.Correlation for this event:
30d3568e-b947-4812-8565-ce474defa2fc_sidecar.jsonat21:02:45 PDTwith{"osarch":"arm64","ptype":"renderer"}.21:02:46.21:02:48.294and reported routes mounted at21:02:48.802.The dominant live process load was not Xcode this time. The app-server had approximately 30 restored task contexts, each with one copy of every MCP-bearing plugin/tool:
| Restored-task helper | Copies | Combined RSS |
| --- | ---: | ---: |
|
codex-securityMCP | 30 | 1.81 GiB || Data Analytics widgets MCP | 30 | 1.35 GiB |
| Sites design-picker MCP | 30 | 1.23 GiB |
| OpenAI API-key confirmation MCP | 30 | 1.21 GiB |
|
node_repl| 30 | 0.43 GiB |The app-server itself used about 3.5-3.7 GiB RSS, and its 153 direct children used about 6.1 GiB. The full Codex process tree used about 16.6 GiB.
This was not a system-wide OOM: the machine has 64 GiB RAM,
memory_pressurereported about 89% available, and swap usage was zero. Instead, Codex had a large per-restored-task helper baseline plus an actively growing renderer/app-server.Only one residual XcodeBuildMCP launcher/worker pair remained (about 142 MiB), and no new
mcpbridgecrash coincided with this renderer crash. That pair also exposed a gap in the initial wrapper: a nestedcodex execinherited a PATH with Homebrew before$HOME/.local/bin, so it bypassed the wrapper.The local emergency circuit breaker is now broader and deliberately reversible:
The four observed plugin MCP identities are also explicitly disabled, and the exact Xcode wrapper is now present in the earlier
$HOME/.npm-global/binPATH location as well. After terminating 120 plugin MCPs, 30 Node REPLs, and the remaining Xcode pair, all targeted helper counts remained zero in a delayed sample.This strengthens the root-cause hypothesis: restored tasks instantiate a full plugin/MCP set per task and retain those processes, while current plugin controls are not reliably re-resolved for restored/nested contexts. XcodeBuildMCP was the first conspicuous family, not the complete defect.
The durable upstream fix should bound this lifecycle: re-resolve current policy on restore, start MCPs lazily, share safe servers where appropriate, reap each task's subprocess tree, and prevent renderer reconstruction from replaying all stale task/tool state at once.
Correction: I have updated the primary issue body because the original “effective local workaround” claim was wrong.
The
$HOME/.local/bin/npxXcode gate was bypassed by nested Codex PATH ordering, and another renderer crash occurred afterward. The issue is not fixed. The latest evidence shows approximately 30 restored task contexts each launching a complete set of four plugin MCP servers plus Node REPL.The broad
plugins = false,apps = false, andnode_repl.enabled = falseconfiguration is only a temporary diagnostic circuit breaker. It has not yet been verified across a clean app-server restart and does not resolve the upstream lifecycle defect.Update: tool catalog restored; broad circuit breaker did not prevent another crash
The temporary
plugins = false/apps = falsediagnostic circuit breaker has been rolled back. Disabling the tool catalog removed functionality Codex is designed to support and did not prevent another renderer failure.Crashpad wrote renderer sidecar
fb55976b-b3bb-486b-8e9f-a331a6ff30fd_sidecar.jsonat2026-07-13 22:08:59 PDT, whileplugins = falseandapps = falsewere still configured. The app had already rewritten Node REPL to enabled, with 12 REPL processes present. The desktop and app-server remained the same long-lived processes.At approximately
22:12 PDT, plugins, apps, remote plugins, Node REPL, and the four observed non-Xcode plugin MCP identities were restored. Only the native Xcode bridge and remotebuild-ios-appsXcodeBuildMCP path remain disabled/gated.The still-running backend immediately began loading the restored tools. A post-change sample found 3 Codex Security MCPs, 6 Data Analytics MCPs, 7 Sites MCPs, 8 OpenAI developer MCPs, 12 Node REPLs, and zero XcodeBuildMCP processes. The backend was about 4.3 GiB RSS with 44 direct children using about 1.8 GiB.
This is not a claim of resolution. It records that the broad disablement was both functionally unacceptable and insufficient to stop renderer crashes. A clean restart is still needed for a fresh process baseline, while the upstream lifecycle defect remains open.
Windows corroboration and a small bounded reproduction on
OpenAI.Codex_26.707.9564.0(Windows 11 Pro for Workstations 10.0.26200, 16 logical CPUs, 64 GB RAM).After one root task and four completed subagents, a single long-lived
codex app-serverhad these direct children:node ./mcp/server.cjs --stdionode ./mcp/server.mjsnode_repl.exeThe five MCP pairs started in clusters that matched the root/subagent launches. All were idle in a 12-second CPU sample and had no TCP connections, but the completed contexts' helpers remained resident.
I retained the oldest root-task MCP pair and REPL, then terminated the later completed-context helpers. Results:
This supports the broader task/subagent lifecycle finding on Windows: completed contexts retain their plugin/MCP and REPL helpers under the app-server. It is not an OS-orphan case because the app-server remains the parent. Project names, local paths, prompts, and logs are omitted.
Deep-dive update: five reproducible renderer-only failures; Xcode is not the trigger
I ran a new read-only investigation on the current macOS build and inspected the packaged Electron/Owl code. This corrects the earlier workaround narrative and separates the verified failure boundary from the still-unobserved native exit reason.
Environment:
26.707.91948(build5440)codex-cli 0.144.5150.0.7871.11526.5.1arm64, 64 GB RAM26.6 (17F113)Reproduced sequence
Five new Crashpad sidecars in one desktop lifetime contained exactly:
They arrived at
23:49:24,23:56:12,00:03:10,00:09:39, and00:17:27PDT. The four recurrence intervals were 408, 418, 389, and 468 seconds (mean about 7m01s). Each was followed 1.3–2.1 seconds later by a new primary React-root render.The same outer desktop process, GPU process, and primary
codex app-serversurvived all five events. This is therefore not a whole-app restart and not a GPU-process restart. It is a primary renderer reported gone followed by automatic recovery.Renderer memory was severe but the final exit reason is still missing:
vmmapmeasured 3.0 GiB physical / 3.6 GiB peak, dominated by Chromium/V8 PartitionAlloc memory tags;This proves rapid multi-gigabyte renderer growth and a repeatable renderer-only failure loop. It does not prove OOM: current Crashpad retained no
.dmp, macOS produced no matching DiagnosticReport, and the plaintext app log does not retain Electron'srender-process-gonereason or exit code.Packaged-code findings
Read-only inspection of the exact installed ASAR verifies:
render-process-gonescheduleswebContents.reload()after 500 ms.thread/list/thread/readwork.unknown conversation/Conversation state not foundpaths are guarded drops/returns, not demonstrated fatal exceptions.In the live log, cross-task
unknown conversationtraffic jumped from roughly 0–2/minute to about 273/minute immediately after several subagents started, before the first failure. After every reload, the app also attempted to resume the same 13 unarchived legacy tasks. Their rollout files total 1.751 GiB on disk; that is only a recovery-scope proxy, not a claim that all 1.751 GiB was decoded into renderer memory.The strongest current working hypothesis is severe renderer memory/event pressure, with global cross-task fanout, broad recovery reconstruction, and retained backend/tool-host state as contributors. Their individual causal contribution and the renderer's final native exit mechanism still require controlled instrumentation.
Xcode and the previous cleanup
chat_processes.jsonrepair previously described never ran. It timed out waiting for a “full quit” condition that also matched old orphan helpers/Crashpad handlers, created no backup, and made no cleanup. It cannot be credited as either a fix or a failed fix.Requested vendor action
Please instrument and harden the renderer/app-server recovery contract:
render-process-gonereason, exit code, renderer PID, Crashpad report ID, JS/native heap, queue depth, payload bytes, and target/owner identity.Related reports now independently cover the same families: #23725 (macOS renderer reset + unknown-conversation state skew), #32339 / #31946 / #32797 (cross-platform retained MCP/Node process pools), and #33521 (the same
26.707.91948UI package crashes a Linux VS Code renderer while rollback to26.707.71524is stable). PR #19753 added MCP cleanup on explicit session/manager shutdown, but the current long-lived desktop lifecycle still retains hosts, suggesting the relevant shutdown boundary is not reached or another ownership path remains.I can provide sanitized timelines, exact packaged-code offsets, process samples, and the
vmmapsummary privately. Raw logs and task files are not attached because they contain private task metadata.Update: crashes continue; paginated history is not in the current desktop/CLI release
The renderer failure loop is still active on the same macOS desktop build (
26.707.91948, build5440; packagedcodex-cli 0.144.5). No newer desktop build is currently being offered to this machine.Continued failures
Since the previous deep-dive comment's
00:17 PDTcutoff, Crashpad recorded 17 additionalptype: renderersidecars: four more through00:48, then 13 more from09:41through15:42:50 PDT. That brings the extended observation sequence to 22 renderer sidecars. I have not individually correlated every later sidecar with a primary-window remount, so this count establishes continued renderer failures rather than claiming that every artifact has a fully reconstructed UI timeline.The strongest fully correlated sample remains unchanged:
2.88 GBworking set /3.93 GBpeak;thread/turns/listrequests and logged 14,522 guardedunknown conversation/Conversation state not foundevents involving 19 conversation IDs.These observations still do not reveal the native exit reason, but they show a persistent renderer-only failure loop under multi-gigabyte renderer growth and broad cross-task recovery activity.
Every local task still uses legacy history
The latest read-only SQLite snapshot contains 7,257 indexed tasks and every row has
history_mode = 'legacy'; there are zero paginated tasks. Inspection of the installed desktop client also found no caller that requeststhread/start.historyMode = "paginated", so newly created desktop tasks continue to default to legacy history.This matters because the current legacy
thread/turns/listpath still has to replay/read legacy rollout history while the renderer reconstructs many tasks. A paginated API call against legacy storage is not the same thing as paginated thread storage.Feature-gate finding
The desktop host sends process-wide
experimentalFeature/enablement/setoverlays after app-server startup. Its current overlay enablesconcurrent_reasoning_summariesandenable_mcp_appseven though the packaged registry classifies both as under-development and default-off in a normal CLI/app-server launch. It also enables app-only surfaces includingwriting_blocksandthread_tools.concurrent_reasoning_summariesfirst appeared in local desktop overlays on July 9 with the0.144.0-alpha.4app-server. This is a hypothesis, not proven causality: concurrent summary fanout may amplify renderer event volume and recovery pressure. Because the desktop's host overlay can supersedeconfig.toml, it is not a reliable local toggle test.Potentially protective features are already active: remote compaction, request compression, image resizing, and deferred MCP tool loading. Conversely,
local_thread_store_compression,runtime_metrics, andmulti_agent_v2are under-development and are not safe or plausible renderer fixes. I have not edited SQLite history modes or enabled those flags.The latest stable standalone CLI does not contain the paginated-history work
The latest public stable CLI release is
0.144.5(rust-v0.144.5, tag commit87db9bc18ba5bc82c1cb4e4381b44f693ee35623). The desktop already bundles that exact version. During this investigation, the active standalone PATH CLI was updated from0.144.1to0.144.5and verified. The desktop still explicitly launches/Applications/ChatGPT.app/Contents/Resources/codex; updating the standalone installation did not replace the desktop app-server and cannot fix its renderer.Two merged
mainchanges directly address the missing bounded-history path:Neither merge commit is an ancestor of the
rust-v0.144.5release tag; the release branch diverged before both changes. The0.144.5release itself contains a dangerous-command-detection fix, not a desktop renderer or history-recovery fix.Requests to maintainers
concurrent_reasoning_summariesdisabled. If there is no improvement, testenable_mcp_appsseparately rather than changing both at once.render-process-gonereason/exit code/Crashpad ID, renderer heap and payload/queue measurements, renderer epochs, subscription cleanup, bounded hydration/backpressure, and a recovery circuit breaker.Raw task histories and logs remain private, but sanitized gate lists, counts, schema output, timelines, and process samples can be provided.