[app][macOS] ChatGPT/Codex crashes (V8 OOM) and hangs in reading_mode::parse_distilled_html (web reader / DOM distiller)

Open 💬 4 comments Opened Aug 18, 2026 by lilhammerfun
💡 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.814.41407 (6720) — also reproduced on 26.810.52044 (6662)

What subscription do you have?

Pro

What platform is your computer?

Darwin 25.5.0 arm64 arm
macOS 26.5.1 (Build 25F80), Apple silicon (arm64), Mac16,10, 16 GB RAM

What issue are you seeing?

The desktop app repeatedly crashes and hangs while using the web-reading / "browse a page" feature.

Crash (7 reports over ~2 days). All are EXC_CRASH / SIGABRT with asi = "libsystem_c.dylib: abort() called". The abort is raised by Node/V8's out-of-memory handler. Triggered-thread stack (innermost first):

__pthread_kill
pthread_kill
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(...)
...
v8::internal::StrongRootAllocatorBase::allocate_impl(...)
... (JIT frames) ...
v8::Function::Call
node::InternalMakeCallback
node::AsyncWrap::MakeCallback
node::worker::MessagePort::OnMessage
node::worker::Worker::Run

So a Node worker thread calls into the Rust reading_mode::parse_distilled_html, which allocates cppgc (Oilpan) objects; a cppgc collection runs, an allocation fails, and V8 aborts the process.

Hang (3 reports). The process becomes unresponsive for ~40-50 seconds. The busy thread is stuck 15/15 samples in:

reading_mode$cxxbridge1$194$parse_distilled_html +11369892
cppgc::internal::BaseObjectSizeTrait::GetObjectSizeForGarbageCollected

At hang time the footprint is only ~827 MB, so this is not a whole-machine OOM — it is cppgc heap exhaustion / a pathological GC pass. The process also reports "Dispatch Thread Soft Limit Reached: 64" and "Workqueue exceeded constrained thread limit (64)" with 147 threads.

What steps can reproduce the bug?

  1. Open the ChatGPT/Codex desktop app on macOS.
  2. Ask it to read / summarize a web page (or use Browse on a large or complex page).
  3. The app either freezes for ~40-50s (beachball) or exits with a SIGABRT crash report.

What is the expected behavior?

Reading a web page should complete (or fail gracefully) without freezing the UI or crashing the app.

Additional information

  • The reading_mode symbols correspond to Chromium's DOM Distiller / Reader Mode: reading_mode.mojom.DistillationEvaluator, chrome-distiller, use_distiller, enable-dom-distiller, reader-mode-readability-distiller-enabled.
  • Root cause appears to be the Rust reading_mode::parse_distilled_html + cppgc (Blink Oilpan) integration building an unbounded object graph for certain pages, causing either cppgc OOM (crash) or a stuck GC pass (hang).
  • Local crash logs: ~/Library/Logs/DiagnosticReports/ChatGPT-.ips and /Library/Logs/DiagnosticReports/ChatGPT__longde.hang.
  • Possibly related: issue #33582 (memory growth / system freeze) and the community thread "ChatGPT Desktop 26.810.50856 crashes after 1-3 minutes — computer-use / sky.node thread exhaustion".

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 9 days ago

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

  • #38867
  • #38566

Powered by Codex Action

lilhammerfun · 9 days ago

Update: still reproduces after clearing user state (sidebar page states + deepseek threads).

Additional evidence from a post-cleanup macOS hang report (process becomes unresponsive ~44s after launch, on every launch):

  1. The busy thread is the MAIN thread (CrBrowserMain), not just a worker:

-[NSApplication run] -> CFRunLoop source0 -> JS callback -> reading_mode$cxxbridge1$194$parse_distilled_html -> cppgc::internal::BaseObjectSizeTrait::GetObjectSizeForGarbageCollected

  1. Severe thread explosion at hang time: 179 "com.apple.NSEventThread", 169 "com.apple.NSURLConnectionLoader", 330 "ThreadPoolForegroundWorker", plus hundreds of caulk/compositor/computer-use threads (thousands of threads total).
  1. The reading_mode / DOM Distiller runs at startup regardless of the browser sidebar state (clearing browser-sidebar-page-states.json does not stop it), so it is invoked as part of app initialization, not a user-triggered browse.

So the distiller (Chromium DOM Distiller, via the Rust reading_mode crate) hangs in cppgc GC on the main thread at startup, independent of user data.

lilhammerfun · 8 days ago

Update: I found a reproducible local trigger and a workaround that stopped the failure loop.

This changes my earlier assessment slightly: reading_mode::parse_distilled_html remains the confirmed OOM/hang site, but the immediate resource explosion on this machine was associated with repeated managed Computer Use service launches.

Trigger

The app itself is installed on the internal disk, but ~/.codex was a symlink to a Codex home on an external APFS volume. CODEX_HOME was unset, so different parts of the app could refer to the same Computer Use runtime using two path spellings:

/Users/<user>/.codex/computer-use/...
/Volumes/<volume>/codex/computer-use/...

During failure, the app launched hundreds of SkyComputerUseService instances within roughly a minute, alongside repeated socket-lock failures, AppleEvent -600 failures, and eventual V8 OOM.

Verified workaround

After fully quitting ChatGPT, I set CODEX_HOME to the canonical physical directory and relaunched:

launchctl setenv CODEX_HOME /absolute/canonical/path/to/codex-home

Across repeated samples covering the previous failure window, SkyComputerUseService remained at one process and the socket-lock / AppleEvent / spawn-loop messages stopped.

For Finder/Dock launches on macOS, a shell startup-file export is not sufficient; the GUI launch environment must receive the variable. If the canonical directory is on an external volume, it must be mounted before ChatGPT starts.

Likely mechanism

Inspection of the installed bundle suggests inconsistent path canonicalization around the managed Computer Use service. If ownership or PID validation compares the symlink spelling with the resolved spelling literally, a healthy child can be rejected and another service spawned.

Potential upstream hardening:

  1. Canonicalize the configured service path and running executable path before validation, or compare filesystem identity.
  2. Add single-flight startup coordination, backoff, and a hard process cap/reaping path for managed Computer Use launches.

This is a locally verified workaround, not an upstream-confirmed root cause, and it may not explain every reading_mode OOM. The distiller may still have an independent memory bug. It may explain one trigger behind the same crash family reported in #38867; #38566 may be a different failure mode.

lilhammerfun · 8 days ago

One investigation-process note, since credit is due: I had previously spent substantial time testing hypotheses with DeepSeek V4 Pro and DeepSeek V4 Flash, but those attempts did not isolate this trigger. ChatGPT/Codex was the tool that connected the Computer Use process storm to canonical CODEX_HOME path identity and then validated the workaround with a controlled A/B test.