Codex Desktop (macOS): renderer OOM crash loop (~5 min) with many concurrent threads — unbounded thread history retention, post-reload refetch storm, 170+ leaked renderer processes

Open 💬 6 comments Opened Jul 23, 2026 by rdylina
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From "About Codex" dialog)?

26.715.72359 (crash evidence below was collected while 26.715.70719 was the running build; both affected). Embedded Codex Framework: 150.0.7871.124.

What subscription do you have?

Pro

What platform is your computer?

Darwin 25.5.0 arm64 arm — macOS 26.5.2 (25F84), Mac16,11 (Mac mini, M4 Pro, 64 GB RAM)

What issue are you seeing?

The main-window renderer process crashes and auto-reloads every ~5 minutes during heavy multi-thread use. The app itself stays up, but the entire window contents disappear and reload as if the app had restarted. Related to #30891 / #31090 / #26362, but filed separately because I have root-cause evidence on the current build: it is an OOM crash loop with three compounding app bugs.

1. Main-window renderer grows to a multi-GB footprint in minutes, then OOM-crashes.

  • Crashpad has accumulated 1,187 sidecars in ~/Library/Application Support/Codex/Crashpad/pending/, all {"osarch":"arm64","ptype":"renderer","ver":"150.0.7871.124"} — 66 on 2026-07-22 alone, with gaps clustering at 4–8 minutes during active use.
  • Watching one cycle live (15 s sampling): fresh renderer reached 1.9 GB RSS at 5m16s of age; vmmap --summary showed anonymous memory (Memory Tag 255, V8/PartitionAlloc) at ~3.4 GB footprint (1.1 GB resident + 2.3 GB swapped); the process died at 9m06s of age and a new Crashpad sidecar appeared within seconds. Crashpad catching it implies an in-process OOM crash, not a jetsam SIGKILL.

2. Post-crash refetch storm makes the loop self-sustaining.

  • The replacement renderer was already at 608 MB RSS 13 seconds after spawn — it immediately re-resumes every thread and re-downloads full histories.
  • In the electron main-process log, of the last 2,000 AppServerConnection response_routed entries, 1,275 were method=thread/turns/list (plus thread/read×108, thread/resume×108). With 10+ active threads whose histories are multi-MB JSON (full delegation transcripts embedded), the renderer re-ingests everything after every reload and sprints back to the OOM ceiling.
  • After each reload the log fills with error [electron-message-handler] Received hook/started for unknown conversation … / Conversation state not found … as in-flight events arrive for state the new renderer no longer has.

3. Renderer process leak starves the machine and accelerates the loop.

  • At time of capture the app had 172 live Codex (Renderer) processes totaling 17.8 GB RSS; many were idle for 14+ hours at 24–150 MB each. Whole app family (renderers + services + codex app-server + cua_node helpers): 24.8 GB RSS on a 64 GB machine.
  • codex app-server (launched with -c features.code_mode_host=true app-server --analytics-default-enable) had 17 h uptime at 4.4 GB RSS and ~180% CPU.
  • System swap was pinned at 6.9/8 GB and macOS logged a JetsamEvent with "largestProcess": "codex". The resulting swap pressure makes the main renderer hit allocation failure sooner, tightening the crash interval.

Crash reports have been uploading from this machine via Crashpad throughout (dumps are removed from pending/ after upload; sidecars remain), so the minidumps should be on your backend under ver 150.0.7871.124, arm64, ptype renderer, 2026-07-18 → 2026-07-23.

What steps can reproduce the bug?

  1. macOS Codex/ChatGPT desktop app, one window.
  2. Run ~10+ concurrent long-running threads/subagents (large histories, continuous streaming; several used Computer Use / browser automation).
  3. Leave the window open. Within ~5–10 minutes the window blanks and reloads; repeat indefinitely.
  4. Observe new *_sidecar.json with ptype: renderer in ~/Library/Application Support/Codex/Crashpad/pending/ at each reload, and ps aux | grep -c "Codex (Renderer)" growing over hours.

What is the expected behavior?

  • Renderer memory for thread UIs should be bounded (virtualize/evict off-screen thread history instead of retaining every thread's full turn list in the DOM/JS heap).
  • After a renderer reload, resume should not re-download all histories for all threads at once (thread/turns/list storm).
  • Idle renderer processes should be reaped; they currently accumulate without bound (172 after ~15 h).
  • codex app-server should not sit at ~180% CPU / 4.4 GB indefinitely.

Additional information

Full quit + relaunch of the app clears the leaked processes and lengthens the interval, but the OOM loop returns once many threads are streaming again. Happy to provide the Crashpad sidecar list, jetsam report excerpts, or run an instrumented build.

View original on GitHub ↗

6 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #34751
  • #33786
  • #33603
  • #34685

Powered by Codex Action

zaptrem · 1 month ago

Cross-linking supply-side evidence for the refetch storm documented here: in #33786 (and my duplicate #34915, now closed into it) there is a symbolized sample profile of what the app-server does to serve each of those thread/turns/list requests — it rebuilds the page by re-parsing the entire rollout JSONL:

codex_app_server::request_processors::thread_processor::build_thread_turns_page_response
codex_app_server::request_processors::build_legacy_api_turns_from_rollout_items
codex_app_server_protocol::protocol::thread_history::ThreadHistoryBuilder::handle_rollout_item

So the thread/turns/list×1,275 flood you measured is doubly expensive: the renderer re-ingests full histories (your OOM loop), and the app-server re-deserializes the complete rollout per request (on my machine: two live ~600 MB rollouts → steady ~210–228% CPU in the app-server from the first minute after launch).

One data point suggesting the same root defect has a second failure mode: my machine (26.715.72359 build 5718, macOS 26.5.2, arm64) runs few concurrent threads but two very large ones, and Crashpad shows no renderer loop — instead 7 sidecars since 07-18, all ptype:"browser", ~8–16 h apart, each matching a SIGABRT .ips with the #34213 signature (node::OOMErrorHandlerv8::ExternalMemoryAccounter::Update on the git worker thread). So: many medium threads → renderer OOM loop (this issue); few giant threads → main-process worker OOM. Both sit downstream of unbounded history rehydration, which #33786 measures on the server side.

rdylina · 1 month ago

Update: process-lifecycle leak confirmed from a second angle — helpers survive full app quit, some for 4–5 days.

After fully quitting the app (verified: 0 Codex (Renderer) processes, main ChatGPT process gone), these were left behind, all reparented to launchd (ppid 1):

  • 41 orphaned cua_node kernel processes (cua_node/bin/node --experimental-vm-modules .../kernel.js), ~0.8 GB RSS combined, with uptimes of up to 5 days 7 hours — i.e. they have been surviving app quits/relaunches for days, not just this session.
  • 14 orphaned browser_crashpad_handler processes from Codex Framework.framework/Versions/150.0.7871.124/Helpers/, including some 5+ days old.

So in addition to the renderer accumulation reported above (172 live renderers after ~15 h inside a running session), Computer Use kernels and crashpad handlers are never reaped on app exit either. Expected behavior: quitting the app should terminate or reap its helper process tree.

Quitting did release everything else: ~17.8 GB of renderer RSS and the 4.4 GB / ~180% CPU app-server were reclaimed; system free memory went from 55% to 76%.

rdylina · 1 month ago

Update: controlled restart experiment quantifies the causal chain — the renderer-process leak is workload-driven and is what re-arms the OOM loop.

After a full quit (which reclaimed everything per my previous comment), I relaunched and instrumented the fresh session (30 s sampling of RSS/process counts, plus a watcher on Crashpad pending/).

Phase 1 — light load (first hour): main-window renderer survived the entire hour with the same PID. RSS ranged 1.3 → 3.5 GB peak → recovered to 2.5 GB (GC reclaimed >2 GB when streaming paused). System memory 76% free, swap quiet. Renderer count crept 21 → 26 (~5/hour). Zero renderer crashes. So the renderer's memory use is recoverable when the system has headroom — the multi-GB peak alone is survivable.

Phase 2 — agent farm resumed (~2.5 h, ~16 concurrent conversations streaming):

  • Renderer process count: 26 → 159 (~50+/hour under load; the leak scales with thread/tool activity, not wall-clock time), total renderer RSS 18.6 GB
  • System free memory: 76% → 25%; swap 8 GB volume ~90% used
  • Renderer crashes resumed (2 in 50 min; ptype: renderer sidecars at 11:04 and 11:54 local), main-window renderer dead after 3.5 h total
  • Replacement renderer reached 2.35 GB within 85 s of spawn (~28 MB/s) from the post-reload resume/refetch of all threads

So the measured chain is: concurrent-thread activity → leaked renderer processes accumulate → system memory/swap exhaustion → main renderer can no longer absorb its own 3–3.5 GB peaks → OOM crash → thread/turns/list refetch storm rebuilds at ~28 MB/s → repeat every few minutes. Fixing renderer reaping alone would likely break the loop, since Phase 1 shows the renderer survives its peaks when the system has headroom.

Separate crash mode captured (distinct bug, happy to file separately): one un-uploaded minidump from this session was not a renderer at all — ~/.codex/computer-use/Codex Computer Use.app/Contents/MacOS/SkyComputerUseService crashed with EXC_BAD_ACCESS / KERN_PROTECTION_FAILURE 232 bytes past a 543 KB worker-thread stack limit (stack overflow), on a thread alongside AXNotificationObserver threads observing Microsoft Outlook — i.e. unbounded recursion while walking a large accessibility tree. Matching SkyComputerUseService-*.ips reports exist from Jul 19/20/22.

rdylina · 1 month ago

@zaptrem Thanks — the rollout re-parsing profile slots right into our measurements: the steady ~170–180% app-server CPU we logged (4.4 GB RSS after 17 h) is well explained by re-deserializing complete rollouts for each of the 1,275 thread/turns/list calls we counted in a 2,000-RPC window.

Our setup is the "many medium threads" shape (10–16 concurrent conversations, multi-MB histories each), and every crash sidecar we've inspected is ptype: "renderer" — none browser — which is consistent with your two-failure-mode split: many medium threads overwhelm the renderer first; few giant threads hit the main-process git worker's external-memory accounting first (#34213). Both downstream of unbounded history rehydration.

One addition from our data: rehydration volume alone didn't kill the renderer when the system had headroom (it peaked at 3.5 GB and GC'd back to 1.3 GB during a light-load hour). It's the leaked renderer processes (26 → 159 in 2.5 h under load, 18.6 GB) exhausting system memory that turns the same peaks fatal. So renderer reaping + incremental/paginated turn serving would likely each independently break the loop.

rdylina · 26 days ago

Update: This regression has accelerated with recent Codex Desktop updates. On the current macOS build (26.727.51351), renderer crashes/reloads now recur every 2–3 minutes during active use, making the application nearly unusable. The main app process remains alive while the window blanks and reloads, and Crashpad continues to show renderer failures. This is materially worse than the earlier ~3–5 minute cadence.