[P0][Regression] macOS app OOM-crashes at startup: external-agent-import parses 1.73 GB from Claude Desktop's app-support directory on every launch
Summary
Since 2026-07-31 ~16:17 local, the Codex/ChatGPT macOS app crashes with a V8 JavaScript heap OOM. This machine had zero crash reports in its entire history before that timestamp and 26 in the following 26 hours.
At startup, external-agent-import (import history from Claude Code / Cursor) opens 4,298 files totalling 1.73 GB from ~/Library/Application Support/Claude/ — a different application's data directory — and parses them into the JS heap. Startup RSS peaks at 2,857 MB, roughly 600 MB below V8's ~3.5 GB ceiling, so every launch is a coin flip.
Reinstalling does not help; none of the driving data is in the app bundle. There is no setting to disable the import scan, so affected users have no workaround.
Environment
| | |
|---|---|
| Version at first crash | 26.727.40816 (build 6067) |
| Version now (self-updated) | 26.727.51351 (build 6119) — still crashes |
| Codex Framework | 150.0.7871.182 |
| OS | macOS 26.4.1 (25E253) |
| Hardware | Mac17,3, arm64 |
Onset — this is a regression
| Time (2026-07-31) | Event |
|---|---|
| — | No crash report had ever been recorded on this machine |
| 16:17:43 | ~/.codex/.sandbox_migration written, contents v1 |
| 16:17 | Bundled plugins newly cached: visualize 1.0.16, sites 0.1.33 |
| 16:17 | ~/.codex/chrome-native-hosts-v2.json rewritten |
| 16:19:08 | First crash ever — 85 seconds later |
| 19:37 | Self-updated 6067 → 6119; crashes continue |
The implicated user data had existed for weeks with zero crashes. The scanning behaviour is what changed, not the data.
Crash signature
<--- Last few GCs --->
[pid:0x12001410000] 4851 ms: Scavenge 3488.3 (3547.5) -> 3488.2 (3547.5) MB,
165.18 / 0.00 ms (average mu = 0.765, current mu = 0.001) allocation failure;
ERROR:owl/common/node_bindings.cc:109] OOM error in V8:
Scavenger: semi-space copy Allocation failed - JavaScript heap out of memory
macOS report: EXC_BREAKPOINT (SIGTRAP), Trace/BPT trap: 5; faulting thread V8Worker or CrBrowserMain. Heap dies at ~3,489 MB every time.
Two distinct regimes observed:
| Regime | current mu | Time to crash | Cause |
|---|---|---|---|
| Startup burst | 0.001 (GC thrashing) | 5–21 s | 1.73 GB bulk read/parse at launch |
| Slow leak | 0.992 (GC idle) | 6 h 52 m | separate, independent defect |
Root cause — measured
lsof polled every 150 ms across a full startup, aggregated by directory:
AGGREGATE OPENED UNDER $HOME DURING STARTUP: 1.72 GB (4,422 files)
1732.4 MB (4298 files) ~/Library/Application Support/Claude <-- 99%
25.2 MB ( 114 files) ~/Library/Application Support/Codex
2.8 MB ( 3 files) ~/Library/HTTPStorages/com.openai.codex
2.4 MB ( 3 files) ~/Library/Caches/com.openai.codex
99% of startup file I/O is another application's support directory.
The files are local_*.json session metadata under~/Library/Application Support/Claude/local-agent-mode-sessions/<uuid>/<uuid>/ —
4,463 files, 1.72 GB — opened on every launch regardless of age.
A second class in the same tree is also read: nested Claude Code transcripts at.../local_<id>/.claude/projects/<encoded-cwd>/<session>.jsonl —
5,870 files, 10.3 GB, nested 14 levels deep. Removing only those extended
survival from ~20 s to ~90 min but did not fix it.
Proof
RSS sampled across startup, before and after archiving 4,418 stale local_*.json (1.69 GB), keeping the last 3 days:
| t | RSS before | RSS after |
|---|---|---|
| 2 s | 1,875 MB | 523 MB |
| 4 s | — | 1,280 MB |
| 6 s | 2,857 MB | 1,250 MB |
| 10 s | 1,548 MB | 663 MB |
| steady | ~450 MB | ~671 MB |
Peak startup RSS: 2,857 MB → 1,280 MB. Five consecutive cold launches afterwards: zero OOMs.
Independent control: renaming local-agent-mode-sessions out of the scan path dropped the import scan from 5,900 ms → 39 ms.
Steps to reproduce
- Install the Codex/ChatGPT macOS app alongside Claude Desktop.
- Use Claude Desktop's local agent mode until
~/Library/Application Support/Claude/local-agent-mode-sessions/holds a few thousandlocal_*.jsonfiles (~1.5 GB+). - Launch the Codex/ChatGPT macOS app repeatedly.
- Startup RSS spikes to ~2.9 GB; a substantial fraction of launches abort with the V8 OOM above.
Suggested fixes
- Do not descend into other applications' support directories.
~/Library/Application Support/Claude/is not user-authored history. - Cap aggregate bytes parsed per scan, not just per-file — the failure is total volume across thousands of small files, not one large file.
- Filter by mtime. Keeping the last few days cut the working set 98% here (4,463 → 45 files) with no loss of useful history.
- Stream / incrementally parse, releasing between files.
- Run discovery in a bounded-heap worker; fail the import gracefully instead of aborting the app.
- Add a user-facing toggle — there is currently no way to disable this scan.
- Cache discovery results; the full scan runs on every launch and on a short repeating interval thereafter.
Notes for whoever picks this up
--js-flags="--heap-snapshot-near-heap-limit=N"is rejected by this build (Error: unrecognized flag) — it is a Node flag, not a V8 flag. A bare--max-old-space-sizeargument is silently ignored.--inspect/--inspect-brkdo work and expose a usable CDP endpoint on the main process.- Disabling the
visualizeandsitesplugins does not help; crashes continued at 5–8 s across repeated trials. - A second, independent slow leak remains: with startup fixed, an instrumented run still reached the ceiling after 6 h 52 m with
mu = 0.992(healthy GC, steady growth). - In-app feedback was also filed with ID
no-active-thread-019fbefd-69f5-79f1-a940-d28ce4a11e44, which has the attached session logs.
This is a shipped regression with a known onset date that renders the app unusable, and it likely affects every user who runs both apps. Requesting priority triage.
9 Comments
ChatGPT on MacOS is freezing because of this for 10 minutes after I launch it
Reproduced on a newer build, with some additional findings — most importantly why this never stops retrying.
Environment
~/Library/Application Support/Claude/local-agent-mode-sessions/— 5.0 GB across 23,171 files (roughly 3× the 1.73 GB reported in the original post).Different OOM signature, same trigger
The GC log shows the heap pinned at the ceiling right before death:
Crash reports show
EXC_BREAKPOINT/SIGTRAPonCrBrowserMaininsideCodex Framework, with the faulting frame undernode::fs::AfterInteger.It is not only a startup crash — it recurs on a ~10 minute cycle
This is worth emphasizing, since the title frames it as startup-only. In one instrumented run the process idled at ~240 MB for 632 seconds, then died. Sampling RSS every 5s, the last reading before death was 241 MB — the jump to ~3950 MB happened in under 5 seconds, in a single allocation burst.
The app log's last entry before every OOM is the same:
Three independent reproductions, same sequence each time.
Why it retries forever
external_agent_config_importsin~/.codex/state_5.sqlitehas 0 rows.That is the completion-record table added in #28396. Because the process is killed before it can persist a record, nothing is ever marked as imported, so the next detect pass runs again — and dies again. That is what turns "slow/expensive startup work" into a permanent crash loop with no user-visible way out.
Related: #26637 and #34449 treat this path as a performance problem. From here it presents as a hard availability bug — #34449 merged 10 days before the OOM reports started, so the configurable detection limits do not cover this case.
Confirmations of things already reported here
--js-flags=--max-old-space-sizeandNODE_OPTIONSare both silently ignored. Three attempts at 8192 and 10240 MB died at 3939, 3946 and 3938 MB respectively — the limit never moves.Isolation
Running the same binary with an empty
CODEX_HOMEstarts and stays stable at ~650 MB, so the app bundle itself is fine.One aggravating factor worth noting separately: the
electron-persisted-atom-statekey in~/.codex/.codex-global-state.json(227 KB, 336 atoms) raises the baseline heap enough to make the app OOM during startup rather than minutes later. Removing that key moved time-to-crash from ~13 seconds to ~10 minutes, but did not fix the underlying crash — the import still kills it on its next cycle.Mitigation, with numbers
Archiving files older than 14 days out of
local-agent-mode-sessions/(17,381 files, 3.86 GB moved; 1.1 GB / 5,794 files left in place):| | before | after |
|---|---|---|
| scan peak | OOM at ~3950 MB | 757 MB / 1074 MB / 1151 MB, memory released each time |
| outcome | dead in 13 s – 11 min | stable, no crashes |
The scan now completes and returns the memory instead of exploding. Same operation, same code path — only the input size changed.
Suggested fixes
Streaming or batching the read would fix the root cause, but two cheaper guards would stop the crash loop on their own:
external_agent_config_importsbefore doing the expensive read, so a crash cannot produce an infinite retry.sessionCount=40says nothing about whether those 40 sessions are 40 MB or 4 GB.Confirming this diagnosis with a strong data point from #37493 (now closed as duplicate of this issue).
Deterministic reproducer: my
~/Library/Application Support/Claude/is 19 GB / 79,740 files — roughly 10× the size reported above. At that size the crash is not a coin flip: the app dies on every launch, ~6–15 s in, on both 26.730.61639 (build 6234) and 26.803.41515 (build 6321). Crash signatures alternate between the V8 heap OOM on CrBrowserMain andEXC_BREAKPOINT (SIGTRAP)in V8 GC code on a V8Worker thread — consistent with dying at slightly different points of the same runaway import.Clean control: the identical builds run fine on my other Mac (M4 Pro, macOS 26.3.1), which has essentially no Claude data. Before finding this issue I'd chased the wrong variables and ruled them out one by one:
CODEX_HOME+ fresh Codex Application Support → still crashes (consistent with the import reading Claude's directory, not Codex state)The data-size correlation is the only variable left standing, and it matches this issue's mechanism exactly.
Last working build here is 26.727.51351; I've pinned it (
chflags uchg+ blockedSUFeedURL) since there's no setting to disable the import scan. Full.ipscrash reports for both crashing builds are attached.An off switch for
external-agent-import(or lazy/bounded import) would resolve this for heavy Claude Code users, who seem to be the population hit hardest.48 GB M3 Max: reversible isolation test confirms the trigger
I ran a controlled isolation test on another affected machine.
Environment
~/Library/Application Support/Claude/local-agent-mode-sessions:local_*.jsonfiles.jsonlfilesBaseline
With the Claude directory in its normal location, build 6234 consistently
terminated after approximately 8–9 seconds:
CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memoryEXC_BREAKPOINT / SIGTRAPCrBrowserMainv8::String::NewFromUtf8,node::StringDecoder::DecodeData, and Node filesystem callbacksBuild 26.803.41515 (6321) also failed in 6–15 seconds when tested with a
separate Electron profile.
Reversible isolation test
lsofthat nothing held the directory open.local-agent-mode-sessionsto a sibling path.Result
stabilized near 509,408 KiB.
This also demonstrates that 48 GB of physical RAM does not protect against the
defect; the limiting resource is the Electron/V8 heap populated by the import.
Could this be treated as a launch-blocking availability regression rather than
only a performance issue? An immediate mitigation could be shipped before the
full streaming fix:
loop.
Third independent confirmation of the root cause — and a new data point on the retry loop.
Build 26.803.61601 (6396) is still affected: two launch crashes on Aug 11 on a 16 GB M-series MacBook (macOS 26.6.1/25G76) —
EXC_BREAKPOINT (SIGTRAP)onCrBrowserMain, uptimes 7.7 s and 14.2 s, faulting stacks inv8::Isolate::LowMemoryNotification/v8::CppHeap::CollectGarbage.Intervention on the same machine, same build, ~25 minutes later: moved every
local_*.jsonolder than 72 h out of~/Library/Application Support/Claude/local-agent-mode-sessions— 2,161 files / 4.13 GiB moved, leaving 38 files / 29 MB. Build 6396 then launched clean on the first try: >75 s uptime, steady RSS ~318 MB (vs ~2.9 GB pre-archive startup peak), zero new crash reports. Only the payload changed; consistent with @santiromer's archive result and @pgolec's rename test.New: after that first successful launch,
external_agent_config_importsin~/.codex/state_5.sqlitestill contains 0 rows. So the missing completion record is not only a crash artifact — even a surviving import doesn't persist one, meaning the full scan apparently re-runs on every launch regardless. A persisted completion record and/or an mtime/byte cap on the scan would each independently mitigate this.No change in importer behavior observed through 6396; nothing in the changelog for 26.803.x either.
Still reproducible in 26.803.81509 (build 6415) — worse: full local state wipe does not help
Confirming this regression persists in the latest build. My data point is a heavier case than the OP's:
~/Library/Application Support/Claude/local-agent-mode-sessions= 3.3 GB across 22,959 files (~1,000 local agent sessions)Captured from a terminal launch:
Crash signature (
.ips):EXC_BREAKPOINT (SIGTRAP)onCrBrowserMain, main-thread stack endingnode::fsread callback →node::StringBytes::Encode→v8::String::NewFromTwoByte→ V8 fatal. The last app-log lines before death are alwaysexternal_agent_import_provider_stage_finished ... providerId=claude-code sessionCount=10 stage=detect, ~2 s before the crash.lsofpolling during startup shows the main process enumerating hundreds of files underlocal-agent-mode-sessions/.Additional findings:
~/Library/Application Support/Codex, allCodex/com.openai.codexcaches,com.openai.codex.plist, HTTPStorages, and~/.codexentirely; the app re-scans Claude's directory and OOMs identically on a 100% fresh profile. Reinstalling the app also has no effect.--js-flags="--max-old-space-size=16384"is ignored — same OOM at the ~3.6 GB ceiling, so there's no user-side launch workaround.NewFromUtf8); since the startup scan was introduced it's a launch crash-loop.Happy to provide full
.ipsreports or run instrumented builds.Another confirmation, and one of the larger payloads reported: on a macOS Apple Silicon machine (heavy Claude user), ~/Library/Application Support/Claude/local-agent-mode-sessions was 21 GB across 148,953 files. ChatGPT/Codex desktop 26.803.41515 (6321) OOM-crash-looped on every launch (dead in <20 s; a lower-RAM Mac showed a blank white window and died even sooner). Moving that directory aside -> the app launches clean and stays stable; restoring ~/.codex sessions afterward is fine. So it is purely the external-agent-import scan volume, not Codex's own state or the ChatGPT account (reproduced across two machines / two accounts). +1 for an off-switch or an mtime/byte cap on the scan.
Update: build 26.810.52044 (6662) still contains the same unbounded Cowork manifest-parse ordering.
A read-only inspection of the currently installed app bundle (
Contents/Resources/app.asar,.vite/build/main-BIHCWhv-.js) shows:Mk(accountOrgDirs)enumerates every*.jsonin each account/org directory and itsagent/subdirectory viazk().Promise.all(t.map(Ik)).IkcallsbE;bEperformsreadFile(path, "utf8")followed byJSON.parse.sessionId.I found no pre-read
stat/mtime filter, file-count limit, per-file size ceiling, or aggregate-byte cap in this path. Therefore, age/session limits applied later cannot bound the initial V8 allocation burst.Build 6662 also exposes
external-agent-import-sync-enabled(default false) for autosync, but that is not a clear “never scan Claude data” guard around this detection path.Important: I am not claiming a fresh OOM reproduction on 6662. After the Aug 11 move-only archive, this machine's live payload is currently small (last measured earlier today: 140
local_*.jsonfiles / 115,778,659 bytes), and I did not restore or modify the protected archive. This is static confirmation that the vulnerable ordering remains in the latest installed build.An immediate safe hotfix would be to stat/filter and enforce an aggregate-byte cap before any content read, replace the unbounded
Promise.allwith limited concurrency, and add an explicit opt-out or isolate discovery from the desktop main process.Confirmed fixed in 26.818.22352 (build 6872) — verified at 3.6 GB scale
Follow-up to my Aug 13 report: today's build resolves this on my machine, and the fix appears deliberate rather than incidental.
Empirical test: I restored my full Claude session store (3.6 GB, ~23k files, 2.3 GB of
.jsonltranscripts — more than the load that crash-looped 26.803) and launched. The app survived, peak RSS ~1.1 GB during the scan, settling at ~495 MB. Previous builds hit the ~3.6 GB V8 heap ceiling and died within 6–16 s. Zero OOM/FATAL lines on a terminal launch.Bundle inspection (
Contents/Resources/app.asar, same read-only method as pkruger1977's Aug 16 comment): the import path is rewritten with explicit budgets —sessionBytes: 16*1024*1024andsessionMessages: 1e4per sessionsessionAttempts: 500plus adirectoryEntriesbudget per scanmaxSessionAgeMsdefault 30 dayshistory-limitskipped-reason with graceful deferral instead of unboundedPromise.allreadFile+parseThe unbounded ordering pkruger1977 found in 26.810.52044 is gone in 6872.
Caveat for the heavy cases in this thread: my store is 3.6 GB — the 19–21 GB / ~150k-file reports may still stress the 500-attempt/entry-budget path differently, so worth re-testing at that scale before closing.