Codex Desktop renderer crashes after MCP/runtime burst with large active thread state
Summary
Codex Desktop renderer crashed and immediately restarted while the main app and app-server stayed alive. This happened while the local profile had a large active thread/history state and several MCP/tool runtimes were being created in a short burst.
This looks related to the local-history/thread-list scalability family, but this case has a concrete Crashpad dump for ptype: "renderer".
Related issues that may share the same root family:
- #24510: unbounded active thread metadata / local history/list processing
- #20435: renderer high CPU while MCP servers are idle
- #12709: progressive slowdown during long MCP-heavy sessions
- #21948: large active session causing global freezes
- #25009: slow/stuck Desktop after large transcript/context events
Environment
- Product: Codex Desktop
- OS: macOS 26.4.1
25E253 - Architecture: arm64
- App process version observed in helper path: Electron helper
149.0.7827.54 - Main Codex process was still alive across the incident
- app-server process was still alive across the incident
What happened
At approximately 2026-06-04 18:07:17 KST, a Crashpad dump appeared:
~/Library/Application Support/com.openai.codex/web/Crashpad/pending/
1bf868d3-c532-4d43-a6b7-a8ef711f673e.dmp
1bf868d3-c532-4d43-a6b7-a8ef711f673e_sidecar.json
The sidecar identifies the crashed process type as renderer:
{"osarch":"arm64","ptype":"renderer"}
The main app and app-server did not crash:
Codex main PID 48458
started: Wed Jun 3 09:58:03 2026
still running after the incident
app-server PID 48524
started: Wed Jun 3 09:58:05 2026
still running after the incident
New renderer processes appeared immediately after the crash:
renderer PID 70099
started: Thu Jun 4 18:07:18 2026
renderer PID 70100
started: Thu Jun 4 18:07:18 2026
So the observed sequence was:
18:07:17 renderer Crashpad dump created
18:07:18 renderer restarted
main/app-server remained alive
Local state size at the time
The local state was large:
active threads: 10,571
active preview: 194.99 MB
active text total: 585.44 MB
archived threads: 6,971
archived preview: 181.42 MB
DB sizes:
~/.codex/state_5.sqlite 1.4 GB
~/.codex/state_5.sqlite-wal 4.2 MB
~/.codex/logs_2.sqlite 2.0 GB
~/.codex/logs_2.sqlite-wal 33 MB
Largest active contributors:
/Users/kangmin/cowork/onto-mcp
3,238 rows / 135.12 MB preview
/Users/kangmin/cowork/wireframe_editor_v2-segment-split
5,280 rows / 28.35 MB preview
Recent thread churn around the crash:
recent 15m updated: 27
recent 15m created: 21
recent 15m preview: 0.65 MB
Runtime burst before the crash
In the minutes before the renderer crash, several node_repl / onto mcp / mcp-clickhouse runtime sets were created:
18:04:12 node_repl + onto mcp + mcp-clickhouse
18:05:29 node_repl + onto mcp + mcp-clickhouse
18:05:35 node_repl + onto mcp + mcp-clickhouse
18:05:36 node_repl + onto mcp + mcp-clickhouse
18:05:40 node_repl + onto mcp + mcp-clickhouse
18:05:51 node_repl + onto mcp + mcp-clickhouse
18:06:23 node_repl + onto mcp + mcp-clickhouse
18:07:17 renderer crash
18:07:18 renderer restart
18:07:33 more onto mcp + mcp-clickhouse processes
18:07:54 more onto mcp + mcp-clickhouse processes
Representative process rows after the crash:
48458 main Codex app-server parent, started Jun 3 09:58, still alive
48524 codex app-server, started Jun 3 09:58, still alive
70099 Codex Renderer, started Jun 4 18:07:18
70100 Codex Renderer, started Jun 4 18:07:18
Symptoms seen by the user
Before and around this incident, Codex Desktop showed visible UI degradation:
- output text streaming lagged
- renderer CPU spiked
- app-server CPU spiked
- GPU/service process showed repeated CPU bursts
Earlier samples in the same investigation showed:
Renderer: up to ~140% CPU, RSS ~1.7-1.8 GB
app-server: up to ~190% CPU, RSS ~790-820 MB
GPU/service: up to ~48% CPU
Why this appears to be a renderer/state projection issue
The MCP processes themselves were not the main CPU consumers at the moment of inspection. The heavier activity appeared in renderer/app-server, while many MCP helper processes were idle or low CPU.
This points to the renderer processing a large and changing local UI/session state rather than a single MCP server doing expensive work.
Hypothesis:
large active thread/history state
+ burst of tool/runtime/session creation
+ renderer receives and reconciles session/list/state updates
-> renderer memory/JS/rendering pressure
-> renderer crash/restart
Inspection commands used
# Crashpad files created recently
find ~/Library/Logs/DiagnosticReports ~/Library/Logs/CrashReporter \
"$HOME/Library/Application Support/Codex/Crashpad" \
"$HOME/Library/Application Support/com.openai.codex/web/Crashpad" \
-type f -mmin -15
# Crashpad sidecar
sed -n '1,220p' \
"$HOME/Library/Application Support/com.openai.codex/web/Crashpad/pending/1bf868d3-c532-4d43-a6b7-a8ef711f673e_sidecar.json"
# Process start times and renderer restart
ps -axo pid,ppid,lstart,etime,%cpu,%mem,rss,command \
| rg 'Codex.app|Contents/Resources/codex app-server|Codex \\(Renderer\\)|Codex \\(Service\\)'
# Local active thread state
sqlite3 -header -column ~/.codex/state_5.sqlite '
SELECT archived, COUNT(*) AS rows,
ROUND(SUM(LENGTH(preview))/1024.0/1024.0,2) AS preview_mb,
ROUND(SUM(LENGTH(title)+LENGTH(cwd)+LENGTH(first_user_message)+LENGTH(preview))/1024.0/1024.0,2) AS text_mb
FROM threads
GROUP BY archived
ORDER BY archived;
'
Expected behavior
The renderer should remain stable when many sessions/tool runtimes are created, even if local history is large.
At minimum, large local history and runtime/session bursts should be handled through bounded projections, pagination, debouncing, or backpressure so that the renderer does not need to eagerly materialize or reconcile an unbounded active working set.
Actual behavior
The renderer crashed and restarted while main/app-server survived. The local state was large, and a burst of runtime/session creation happened immediately before the crash.
Suggested fix direction
This likely needs the same general direction as #24510 but applied explicitly to renderer-facing state:
- keep raw local history separate from renderer/UI projections
- bound the active list payload sent to the renderer
- debounce/coalesce runtime/session list updates during bursts
- avoid sending large
preview/first_user_messagefields unless needed for visible rows - make renderer rehydration incremental after reconnect/restart
- expose diagnostics for oversized active state or problematic sessions
The invariant should be:
The renderer should receive a bounded view of local state, not the full local history surface.This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗