Since updating Codex Desktop on August 25, I experienced three unplanned full-app shutdowns. Every active local task was interrupted, including child tasks.
A read-only forensic review of desktop logs, Crashpad metadata, Windows event logs, rollout JSONL, and the local thread-history databases found two connected problems:
- Every confirmed shutdown occurred 573–790 ms after a successful built-in-browser
tab.close()operation. - After restart, the rollout writer reused the final pre-crash ordinal. The durable-history projector rejected that duplicate record and remained permanently behind the raw JSONL, producing stale task state and resume drift.
A separate Store update also forcibly terminated the running application, but that event was distinguishable from the three later crashes.
Environment
- Windows 11 Home 25H2, build
26200.9168, x64 - Codex MSIX package:
26.820.7780.0 - Bundled browser tooling:
26.820.60940 - Bundled Codex core/app-server:
0.150.0-alpha.8 - Executable runtime version:
151.0.7922.170 - 32 GB RAM
- Hardware acceleration enabled
- Package status reported as healthy
- OpenAI executables have valid Authenticode signatures
Impact
When the desktop main process exits:
- All active tasks associated with that desktop host are interrupted.
- Root and child turns can be left without a completion or abort event.
- Relaunch reports the latest turn as interrupted.
- Recovery may reconstruct work from stale projected history.
- Previously running child tasks can become orphaned while replacement work is started.
- This results in repeated actions, lost transient state, and semantic drift after resume.
Confirmed incident timeline
Successful tab.close() completion |
Crashpad capture | Delay |
|---|---|---|
| 2026-08-26 00:20:59.564 UTC | 00:21:00.354 UTC | 790 ms |
| 2026-08-26 07:28:59.500 UTC | 07:29:00.073 UTC | 573 ms |
| 2026-08-26 11:42:24.657 UTC | 11:42:25.425 UTC | 768 ms |
Each browser-tool call returned successfully:
status=completed
isError=false
openTabIds=[]
The final desktop lifecycle sequence was essentially identical in all three incidents:
debugger listener unregistered, reason=target-close
browser-use active state changed to false
iab rejected tab for route, tabRouteKey=null
renderer/webview disposed
browser sidebar guest torn down
sidebar webview removed
browser sidebar page closed
browser tab lifecycle action=closed
<desktop log ends abruptly>
Crashpad then recorded:
{
"capture_kind": "crash",
"osarch": "x86_64",
"ptype": "browser"
}
In Chromium/Electron terminology, ptype=browser identifies the top-level browser/main process, not merely the controlled page renderer. This explains the process-wide blast radius.
There was no graceful app-server transport shutdown before these three crashes.
Reproduction pattern
The observed pattern is:
- Start a local Codex task that uses the desktop app’s built-in browser.
- Perform browser actions.
- Close the tool-controlled tab with
tab.close(). - The close operation reports success.
- Intermittently, the entire desktop application exits within one second.
- Reopen the same task.
- The task appears interrupted, and subsequent recovery can use stale or incomplete durable history.
The failure is nondeterministic. On the current release, four successful tab-close operations were retained locally: three were followed by a crash and one was not. This is a small local sample, not an estimated population failure rate.
The same route warning also appears during successful closes, so tabRouteKey=null is not sufficient to cause the crash by itself. It is most likely a breadcrumb inside a teardown path that has a timing-dependent lifecycle, reentrancy, or double-disposal problem.
Evidence of a post-crash recovery defect
After restart, the first new rollout record repeated the last pre-crash ordinal.
Simplified example:
Last valid pre-crash record: ordinal 4774
First post-restart record: ordinal 4774
Projector expected: ordinal 4775
The app-server then repeatedly logged errors equivalent to:
failed to project durable rollout:
thread history projection expected ordinal 4775, got 4774
Another affected history produced:
expected ordinal 826, got 825
Across the affected histories, the read-only snapshot found:
- 3 histories with ordinal discontinuities
- 4 duplicated restart-boundary ordinals
- 1,224 retained durable-projection rejection warnings
- Raw JSONL continuing normally after the duplicate
- SQLite projection remaining frozen at the duplicate boundary
- A projected turn still marked
inProgresseven though later raw JSONL containedtask_complete
The resulting state is effectively:
Raw rollout JSONL:
continued activity and later terminal events
Projected SQLite/UI state:
original turn still in progress, with later records unavailable
The SQLite databases themselves passed structural integrity checks. This is therefore a logical checkpoint/cursor inconsistency, not physical SQLite corruption.
The current codex doctor checks also did not detect this condition. Its relevant checks reported rollout/database parity and thread-history integrity as healthy because they validate file inventory and SQLite structure. They do not appear to validate:
- Per-record ordinal monotonicity
- Projector byte-offset lag
- Raw-versus-projected terminal-state parity
- Stale
inProgressturns - Repeated durable-projection failures
Why this causes resume drift
The crash and the drift are separate stages:
Successful tab close
↓
Electron main/browser-process crash
↓
Active root and child turns end without terminal records
↓
Restart reuses the previous rollout ordinal
↓
Durable projector rejects the duplicate record
↓
Raw JSONL advances while projected history remains stale
↓
Resume reconstructs from incomplete state
↓
Orphaned/repeated work and semantic drift
At the first confirmed crash, one root turn and three child turns were active. All four were left without task_complete, turn_aborted, a completion timestamp, or a final-agent item.
Relationship to the August 25 update
The local failure frequency increased sharply after the August 25 update. The public August 25 changelog also mentions changes involving site tools/WebMCP in the desktop built-in browser.
That is only temporal correlation. It does not prove that WebMCP caused the crashes or that the public changelog entry maps directly to the affected internal teardown code.
There is also one older abrupt AppX-container termination, on an earlier build, occurring approximately 854 ms after the same successful browser-tab-close sequence. No Crashpad report or dump survived for that occurrence, so it cannot be classified with the same certainty.
The careful conclusion is therefore:
The current update appears to have exposed or substantially increased the frequency of an existing intermittent browser-tab teardown race. The available evidence is not sufficient to claim that the defect was first introduced by this exact release.
Separate forced-update shutdown
At installation time, Windows AppX recorded:
ForceTargetApplicationShutdownOption
while replacing the previous Codex package with the current one.
That shutdown differed from the later crashes:
- The old application logged a graceful app-server transport stop.
- The replacement build launched seconds later.
- No Crashpad artifact was created.
- Windows explicitly recorded the update operation.
This is a separate reliability problem: Store activation can interrupt active work even when the app is otherwise healthy. Updates should ideally be deferred while turns are running or preceded by a durable checkpoint and explicit recovery handling.
Explanations not supported by the evidence
No matching evidence was found for:
- A fixed session or process timeout
- Power loss, sleep, resume, reboot, or manual Windows shutdown
- Windows resource exhaustion or OOM termination
- GPU reset, WHEA error, or display-driver failure
- Defender, ASR, Controlled Folder Access, AppLocker, or Code Integrity blocking
- Network failure at the crash boundary
- App-server panic or transport failure preceding the desktop exit
- An AppX update during any of the three Crashpad incidents
- Context-window exhaustion
This also does not look like normal context compaction. The affected tasks were below their configured limits, the limit flags were false, and no compaction event aligned with the crashes. OpenAI’s compaction documentation describes compaction as preserving the state required for later turns; it should not produce a local browser-process Crashpad event.
Confidence assessment
- High confidence: Built-in-browser tab teardown is the immediate trigger for the three confirmed crashes.
- High confidence: The top-level Electron/Chromium browser process is crashing.
- Conclusive from local state: Restart duplicates the previous rollout ordinal and stalls durable-history projection.
- High confidence: The stalled projection materially contributes to resume drift.
- Medium confidence: The native defect is a teardown lifecycle, reentrancy, or late-callback race.
- Not established: The precise native exception, module, or source line. Symbolicated minidumps are required.
- Not established: That the latest update originally introduced the defect; it may instead have increased its frequency.
Requested engineering investigation
Could OpenAI engineering please:
- Correlate and symbolicate the three Crashpad browser-process reports by timestamp and build.
- Inspect close ordering among debugger/CDP detachment, route metadata, PiP state, renderer disposal, sidebar teardown, and guest
webContentsdestruction. - Make browser-tab teardown idempotent and fence late callbacks after guest destruction.
- Prevent a browser guest/tab failure from terminating the Electron main process.
- Derive the next rollout ordinal from the final valid durable record after an unclean restart.
- Make rollout append and projection checkpoints crash-consistent.
- Add safe recovery when the projector expects
Nbut encounters a duplicated boundary record atN-1. - Explicitly mark unfinished root and child turns as host-crash interruptions.
- Reattach or retire orphaned child tasks before creating replacement executions.
- Extend
codex doctorwith ordinal-monotonicity, projection-lag, terminal-state parity, stale-turn, and recent projection-error checks. - Defer Store package activation while tasks are active, or checkpoint and restore active work before allowing forced replacement.
I have three Crashpad report identifiers and the matching log/event slices available for OpenAI through a private channel. I am intentionally not posting raw logs, rollout transcripts, databases, paths, or identifiers publicly.