Codex App update left old crashpad helper; relaunch could no-op until clean restart

Open 💬 3 comments Opened May 30, 2026 by heartInsert
💡 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?

Installed app version from /Applications/Codex.app metadata:

26.527.31326

A stale helper process was still annotated as the previous version:

_version=26.519.81530

What platform is your computer?

macOS 26.4.1 (25E253)
Darwin 25.4.0 arm64

What issue are you seeing?

After a Codex Desktop auto-update, launching Codex from the app icon could appear to do nothing: no usable window came up, while old Codex-related helper processes were still present. A clean launch via open -a Codex restored the app, and the current main process/app-server/renderer came up normally.

The notable local evidence is that after the app was already updated to 26.527.31326, an old crashpad helper from 26.519.81530 was still alive and orphaned under launchd:

PID   PPID  STARTED                         ELAPSED       COMMAND
1723  1     Fri May 29 19:02:52 2026        01-00:17:38   /Applications/Codex.app/Contents/Frameworks/Electron Framework.framework/Helpers/chrome_crashpad_handler ... --database=/Users/mac/Library/Application Support/Codex/Crashpad ... --annotation=_productName=Codex --annotation=_version=26.519.81530 ...

Current post-recovery app processes were from the new app install:

15217  1      Sat May 30 19:13:04 2026  /Applications/Codex.app/Contents/MacOS/Codex
15277  15217  Sat May 30 19:13:07 2026  /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled

There was also a live extension-host process:

14535  1555  Sat May 30 19:11:14 2026  /Users/mac/.codex/plugins/cache/openai-bundled/chrome/latest/extension-host/macos/arm64/extension-host chrome-extension://...

I am not claiming the crashpad helper is definitely the process holding Electron's single-instance lock. The observed user-visible behavior is consistent with stale instance/router/lifecycle state after update, and the leftover old-version crashpad helper is a concrete signal that the update/quit path did not fully clean up Codex-owned child/helper processes.

Local log DB evidence

~/.codex/logs_2.sqlite is valid but large:

$ du -h ~/.codex/logs_2.sqlite
728M    /Users/mac/.codex/logs_2.sqlite

$ sqlite3 ~/.codex/logs_2.sqlite 'PRAGMA integrity_check; SELECT count(*) FROM logs;'
ok
254104

This may be separate from the launch-no-op symptom, but it matches other reports where logs_2.sqlite growth/corruption contributes to startup or performance problems.

Steps to reproduce

I do not have a deterministic reproduction yet. The sequence was approximately:

  1. Use Codex Desktop normally across an app auto-update from 26.519.81530 to 26.527.31326.
  2. Quit/relaunch Codex.
  3. Launching from the app icon appeared to do nothing/no window appeared.
  4. Inspect processes and observe stale Codex helper process from the previous version.
  5. Run open -a Codex; the app then launched successfully.

Expected behavior

After auto-update or quit/relaunch:

  • old-version Codex helper/child processes should not survive indefinitely;
  • a stale helper/router/single-instance state should not make the app appear to launch with no window;
  • if another instance/router is active, the app should either focus the existing window or show a user-facing recovery/error state;
  • rebuildable log state such as logs_2.sqlite should not permanently block startup if it is corrupt, and large log DBs should be bounded/rotated.

Related issues

This looks related to, or at least in the same failure family as:

  • #23917: update followed by app restart failure with logs_2.sqlite corruption
  • #24001: logs_2.sqlite corruption prevents app-server readiness
  • #11324: Codex App process/MCP cleanup gaps, including orphaned chrome_crashpad_handler after quit
  • #12974: background/no-UI launch with Another router is active on Windows
  • #20213 / #21134: large logs_2.sqlite and TRACE log churn impacting performance

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 3 months ago

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

  • #23845
  • #24072
  • #23917

Powered by Codex Action

javenfang · 2 months ago

Additional evidence: deterministic 99% CPU startup hang from a cross-version stale crashpad handler

Hitting what looks like the same failure family on macOS, with a more severe symptom (full main-process hang, not just a no-op launch) and a deterministic local reproduction. Sharing detailed evidence and two controlled experiments that may help pin the cause.

Environment

  • Codex App: 26.602.30954 (3575)
  • Chromium framework auto-updated 148.0.7778.179 → 149.0.7827.54 (Sparkle), after which every launch hung
  • macOS 26.3 (25D125), Darwin 25.3.0, Apple M4 Pro (Mac16,8), arm64 (native; not Rosetta)
  • App bundle codesign valid + notarized; not a signature/Gatekeeper issue

Symptom

After the auto-update to 149, launching Codex pegs one core at ~99% CPU on the main thread and the UI never becomes responsive (full hang). Force Quit + relaunch reproduced it every time for ~1.5 hours.

Root-cause evidence

1. The main process spins in main-process JS (Node/V8) — macOS cpu_resource spindump:
90s CPU over 91s wall, single thread, ~99%. Heaviest stack (symbol names approximate; key frames):

ChromeMain
  -[NSApplication run] → _DPSNextEvent → CFRunLoop
  __CFRunLoopDoSource0 → __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
    uv_run → uv__run_check → node::Environment::CheckImmediate
    node::InternalMakeCallback → node::InternalCallbackScope::Close
    v8::Promise::Resolver::Reject
      <same anonymous JIT frame repeated ~17 levels>   ← infinite recursion / synchronous retry

The repeated identical JIT frame under a Promise::Reject inside the uv check-immediate phase is the signature of a synchronous reject→retry loop that never yields, so the CFRunLoop SOURCE0 callout never returns and the UI is wedged. Two separate spindumps were byte-for-byte identical → fully deterministic.

2. The app's own crashpad handler crashes on every launch:

FATAL third_party/crashpad/crashpad/handler/mac/exception_handler_server.cc:76
Check failed: kr == KERN_SUCCESS.
mach_port_request_notification: (os/kern) invalid capability (20)

(version 149 handler; one crash dump pair per launch — consistent with #25921's dump pileup.)

3. Stale OLD-version crashpad handlers were orphaned under launchd:
browser_crashpad_handler processes from the previous 148.0.7778.179 build were still alive (PPID=1), sharing the same --database=.../com.openai.codex/web/Crashpad. They were created by earlier 148 sessions that ended abruptly (Force Quit/crash), survived the bundle replacement (deleting the on-disk 148 framework does not kill already-running processes), and survived every Force Quit.

Fix that worked

kill the stale 148 browser_crashpad_handler processes, then relaunch → 149 launches normally, no spin, handler no longer crashes.

Two controlled experiments (to isolate the cause)

  • global-state is NOT the cause. Restored the full pre-existing ~/.codex/.codex-global-state.json (~92 KB, all projects/connections) with the stale handlers already gone → launches cleanly. So this symptom is not driven by global-state / logs_2.sqlite content.
  • Same-version orphans are benign; the trigger is the cross-version stale handler. Force-killed the running main process to create a fresh same-version (149) orphan handler, then relaunched → no hang, new handler did not crash. The original hang only occurred while the old-version (148) orphan was present, and stopped the instant it was killed.

Caveat: the 148 binary was removed by the update, so I could not recreate a 148 orphan to run the final gold-standard test (148-orphan + 149-app). But the hang correlated exactly with 148-orphan presence and disappeared immediately on its removal.

Suggested fixes

  • On startup/update, reap or refuse to coexist with old-version Codex helper processes (especially browser_crashpad_handler) that survived a previous version.
  • Make crashpad handler init failure (mach_port_request_notification / bootstrap collision) non-fatal / non-spinning for the browser main process, instead of an unbounded synchronous retry.

Related: #25259, #25882, #25921, #11324.

javenfang · 2 months ago

Correction / follow-up to my earlier comment here: the "stale crashpad helper" angle was a red herring.

On a fresh recurrence I killed every Codex process (zero orphaned browser_crashpad_handler left) and the startup hang still reproduced 100% — so it was never the crashpad helper. By single-key isolation the actual cause is a global-state key:
electron-persisted-atom-state → heartbeat-thread-permissions-by-id. Removing only that key fixes the ~100% main-thread spin while keeping everything else intact.

Filed with full evidence (spin stack, isolation method) as a dedicated issue: #27298.