ChatGPT Desktop for macOS: deterministic main-process V8 heap OOM at startup (builds 6644 and 6662)

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

Summary. The ChatGPT desktop app (com.openai.codex) dies 7 to 17 seconds after every launch. The
crash reporter shows EXC_BREAKPOINT (SIGTRAP) on CrBrowserMain, but the underlying failure is a
JavaScript heap out-of-memory in the Electron main process. The heap climbs from zero to the
~3.9 GB ceiling in under 7 seconds and V8 aborts. The allocation runaway is silent: fewer than 100 log
lines are emitted before death and none of them repeat.

This is not the computer-use thread-exhaustion leak reported for this same build train. Thread
count is flat across every crash. See "Distinguishing this from the known report" below.

---

Environment

| | |
|---|---|
| App | ChatGPT.app, bundle id com.openai.codex |
| Versions affected | 26.810.50856 (build 6644) and 26.810.52044 (build 6662) |
| Codex Framework | 151.0.7922.137 |
| OS | macOS 26.6 (25G70) |
| Hardware | Mac16,12 (MacBook Air, Apple M4), 16 GB RAM, arm64 |
| Code signing | Team 2DC432GLL2, SIP enabled |

Incident identifiers

  • ABB9BFB7-E22A-4327-BBBA-943F6B88C6C4
  • F0C7CF4C-2E4D-462A-AFF1-7507DCBA41E4
  • Crash Reporter Key: 3BC8D0AF-8D22-F1E5-3609-041FD3753DFE

---

The actual error

Launching the binary directly from a terminal (ChatGPT.app/Contents/MacOS/ChatGPT) surfaces the error
that the crash reporter hides:

<--- Last few GCs --->
[pid:0x...]  6605 ms: Mark-Compact (reduce) 3912.4 (3927.5) -> 3912.4 (3927.2) MB,
             pooled: 0.0 MB, 13.28 / 0.00 ms (average mu = 0.187, current mu = 0.001)
             last resort; GC in old space requested
[pid:0x...]  6618 ms: Mark-Compact (reduce) 3912.4 (3927.2) -> 3912.4 (3927.0) MB,
             pooled: 0.0 MB, 12.69 / 0.00 ms (average mu = 0.104, current mu = 0.001)
             last resort; GC in old space requested

ERROR:owl/common/node_bindings.cc:109] OOM error in V8:
CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

Two separate runs reached 3887.9 MB at 5956 ms and 3912.4 MB at 6605 ms respectively. No
<--- JS stacktrace ---> block is emitted, so the retaining path is not recoverable from the log alone.

Faulting stack

Identical, frame for frame and offset for offset, in every crash report collected, across both
builds:

0  <unsymbolized>                                          (fatal handler)
...
6  v8::String::NewFromUtf8(v8::Isolate*, char const*, v8::NewStringType, int) + 328
7  node::StringDecoder::DecodeData(v8::Isolate*, char const*, unsigned long*) + 1028
8  node::StringDecoder::DecodeData(v8::Isolate*, char const*, unsigned long*) + 564
9  _register_external_reference_string_decoder(...) + 916
10-16 ???                                                  (JIT frames)
...
20 node::InternalCallbackScope::Close() + 400
21 node::fs::FSReqPromise<...>::SelfSize() const + 636
22 node::fs::AfterInteger(uv_fs_s*) + 204
23 node::MakeLibuvRequestCallback<uv_fs_s, void (*)(uv_fs_s*)>::Wrapper(uv_fs_s*) + 204
24 uv__work_done + 172
25 uv__async_fork + 864
26 uv__io_poll + 1348
27 uv_run + 972

Read bottom-up: an async filesystem request completes, its JS callback runs, string decoding of the
result triggers the allocation that pushes the heap over the limit. The fatal handler fires inside the
fs completion callback. That makes an fs read path in main-process startup the prime suspect, though
the specific call site is not identifiable without a heap snapshot.

Distinguishing this from the known report

There is an existing community report of build 26.810.50856 crashing after 1 to 3 minutes via
computer-use worker-thread accumulation (~2.5 threads/sec, ~70 MB/sec). This is a different bug.

| | Known thread-leak report | This bug |
|---|---|---|
| Time to death | 1 to 3 minutes | 7 to 17 seconds |
| Thread count | grows unbounded | flat, 57 to 69 |
| computer-use threads in crash log | many | 0 or 1 |
| Allocation rate | ~70 MB/sec | ~600 MB/sec |

Thread counts measured across nine pre-intervention crash reports: 68, 65, 66, 69, 65, 67, 63, 65, 65.
computer-use thread counts in the same nine: 0, 0, 1, 0, 0, 0, 0, 1, 1. Nothing accumulates.

Reproduction and bisection

Nine crash reports were produced on a single day with no user intervention, all with the identical
signature above, spanning both builds 6644 and 6662. The app binary was unmodified since installation,
so no app update coincides with onset. Six further crashes were then reproduced under controlled
conditions.

Hypotheses eliminated, each by direct test:

  1. App version. Identical crash on 6644 and 6662.
  2. Large session rollout files. The two outliers (8.19 MB and 7.31 MB .jsonl, versus <1 MB for

all others) moved aside. Still crashed.

  1. Computer Use helper. ~/.codex/computer-use/ removed entirely. Still crashed.
  2. Stale helper processes. All Codex Computer Use / SkyComputerUseClient processes killed.

Still crashed.

  1. Avatar overlay restore. electron-avatar-overlay-open set false and

electron-remote-hosted-pip-task-visibility-state cleared. Still crashed.

The state bisection that isolated it:

| Test | CODEX_HOME | ~/Library/Application Support/Codex | Result |
|---|---|---|---|
| 1 | real | real | crash, ~7 s |
| 2 | empty | real | crash |
| 3 | real | empty | crash |
| 4 | empty | empty | survives, 1 min 7 s, RSS 614 MB falling to 340 MB |

Neither store alone is sufficient to trigger it and neither alone is sufficient to fix it. The two
stores appear to mirror the same poisoned data, so whichever survives re-seeds it. Clearing both
breaks the cycle.

Workaround

Quit the app, then move both state locations aside:

pkill -x ChatGPT; sleep 2
mkdir -p ~/chatgpt-fix
mv ~/Library/Application\ Support/Codex ~/chatgpt-fix/
mv ~/.codex/.codex-global-state.json ~/chatgpt-fix/
mv ~/.codex/cache ~/chatgpt-fix/
open -a ChatGPT

Important caveat observed in practice. After the move, the app still crashed four more times over
about three minutes while rebuilding its state, then stabilised on its own and has not crashed since.
Four subsequent launches, including a clean relaunch via Finder, all survived with RSS settling around
200 to 260 MB and trending down. Users applying this workaround should attempt several launches before
concluding it failed. Why the first launches after the wipe still crashed is not established.

~/.codex/sessions/, auth.json and plugins/ are untouched by the above, so history, login and
installed plugins survive.

---

Secondary bug found along the way: unbounded PiP bootstrap retry

Independent of the OOM, when the app runs against a fresh CODEX_HOME the Computer Use bootstrap
enters a retry storm with no backoff. One 30-second run logged 58 failures across many dispatch
threads:

RemoteHostedPIPContent CUAService bootstrap failed:
  Error Domain=NSOSStatusErrorDomain Code=-1712 "errAETimeout: the AppleEvent timed out"
RemoteHostedPIPContent CUAService bootstrap failed:
  Error Domain=RemoteHostedPIPContent Code=-10005 "Remote hosted PiP is unavailable."

Contributing factors and related observations:

  • sky.node -[RemoteHostedPIPContentService sendBootstrapToServiceWithProcessIdentifier:rendezvousPort:attempt:]

appears on a live thread in the crash reports, sending AppleEvents.

  • The unified log shows AESendMessage: returning procNotFound because destPort == NULL for the helper

pid, i.e. the target process is gone or unreachable.

  • TCC returned denied for kTCCServiceAccessibility for this app (auth_value 0), while

kTCCServiceScreenCapture was granted. Computer Use cannot function in that state, and the app does
not surface this to the user.

  • Helper processes named Codex Computer Use survive the parent's death and were observed still

running after the app exited, which likely makes the next launch's bootstrap fail too. This matches
the "leaves stale helpers" behaviour already reported separately.

Also seen roughly 200 ms before the OOM in one run, from the overlay renderer:

[electron-message-handler] Request failed method=fs/readFile
  error={"code":-32603,"message":"No such file or directory (os error 2)"}
  rendererWindowAppearance=avatarOverlay rendererWindowVisible=false

Given that the faulting stack is inside an fs completion callback, a failing fs/readFile from the
avatar overlay immediately prior is worth checking, though causation is not established.

---

Suggested next steps for triage

  1. Ship a --heapsnapshot-near-heap-limit path, or emit the <--- JS stacktrace ---> block on main

process OOM. Right now the failure is undiagnosable from the client side.

  1. Add a bound and backoff to RemoteHostedPIPContentService bootstrap retries, and tear down helper

processes on parent exit.

  1. Add a size or shape guard on whatever startup path reads and string-decodes local state, so a

poisoned entry degrades instead of aborting the process.

  1. Surface denied Accessibility permission in the UI rather than failing silently.

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 10 days ago

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

  • #38557
  • #38037

Powered by Codex Action

kulturfenster · 6 days ago

Same deterministic OOM here, on a newer build than the two in the report, so this is not fixed in 6892.

Environment

  • ChatGPT.app 26.818.31338 (build 6892), self-updated 2026-08-21 16:45 local
  • macOS Darwin 25.5.0, Mac mini, 48 GB RAM (so no system memory pressure — 22 GB free at crash time)
  • First crash 31 minutes after that update; 12+ crashes since, no successful session

Signature — identical in every ~/Library/Logs/DiagnosticReports/ChatGPT-*.ips:

exception: EXC_CRASH (SIGABRT), asi: "abort() called"
faulting thread: V8Worker
  abort
  node::OOMErrorHandler(char const*, v8::OOMDetails const&)
  reading_mode$cxxbridge1$194$parse_distilled_html
  reading_mode$cxxbridge1$194$parse_distilled_html
  v8::CppHeap::CollectGarbageInYoungGenerationForTesting(...)

Three of the crashes fault in a thread named computer-use instead of V8Worker, otherwise identical.

Growth is linear, ~105 MB/s in the Electron main process. Sampling RSS of /Applications/ChatGPT.app/Contents/MacOS/ChatGPT every 5 s from launch:

+06s   632 MB      +46s  2957 MB
+11s   644 MB      +51s  3514 MB
+16s   835 MB      +57s  4046 MB
+21s  1377 MB      +62s  4579 MB
+26s  1943 MB      +67s  5114 MB
+31s  2439 MB      +72s  5633 MB   -> crash

Crash lands at 71–80 s after launch, every time.

Three things that did NOT help, each verified:

  1. Not caused by local state. Launching with a completely empty CODEX_HOME (CODEX_HOME=/tmp/empty /Applications/ChatGPT.app/Contents/MacOS/ChatGPT) reproduces the same linear leak and the same crash at 80 s. No plugins, no MCP servers, no sessions loaded.
  2. The documented workaround did not stabilize it. Moving ~/Library/Application Support/Codex, ~/.codex/.codex-global-state.json and ~/.codex/cache aside, then four consecutive launches over ~7 minutes: all four crashed with the same OOM signature, no convergence. Reverted.
  3. Raising the heap ceiling does nothing--js-flags="--max-old-space-size=16384" is ignored; the process still dies around 6 GB RSS, same stack.

Point 1 seems worth emphasizing: with an empty CODEX_HOME there is no user data left to decode, yet the leak is unchanged. That argues against the stored-state theory and points at something in the startup path itself.

Happy to run further instrumentation or provide a full .ips if useful.