[macOS Desktop] Reboot can switch app-server runtime and wedge paginated history at a duplicate ordinal
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
Environment
- OS:
Darwin 27.0.0 arm64 arm(macOS) - Codex Desktop:
26.818.41509(build6962) - Bundled CLI:
codex-cli 0.149.0-alpha.4.1 - Local Desktop thread history mode:
paginated
Summary
After a normal macOS restart, Codex Desktop can reopen a paginated thread with an older
conversation snapshot, stop responding, or fail to recover it. The canonical rollout JSONL
still contains the newer turns, but the Desktop history projection stops advancing and the UI
serves stale history.
This is not limited to a single missing file. The observed failure is a restart/login bootstrap
race: the app-server runtime selected before reboot is not guaranteed to be the runtime selected
after reboot. When the second runtime resumes the same paginated rollout, it can write a record
with an ordinal already used by the previous runtime. The projection then waits for the next
ordinal forever.
Observed errors
Depending on which action is attempted, the Desktop UI shows variants of:
failed to resolve rollout path ... file does not existno rollout found for thread id ...invalid paginated history lineage ... missing source rollout恢复对话失败(conversation recovery failed)
In another affected state, the thread remains on “thinking” without producing a response, and
retrying reports that the session is already open in another application.
Reproduction timeline
- Start a long-running local paginated Desktop thread and let it write multiple turns.
- Leave the thread's rollout and state databases intact.
- Restart macOS normally.
- Launch Codex Desktop and open/continue the same thread.
- Observe that the Desktop app-server may be launched from a different runtime than before
reboot. The resumed rollout can contain a duplicate ordinal (for example, a valid record at
ordinalNbefore reboot and a differentthread_settings_appliedrecord at the same ordinal
Nafter reboot). - The projection cursor remains at the earlier boundary (expected
N+1), while the raw rollout
continues to grow. Opening the thread shows older history and follow-up/retry may fail.
The same class of failure is likely when switching accounts or otherwise rebuilding the GUI
session, although the clean-restart path above is the independently verified reproduction.
Evidence from one affected thread
- The raw rollout remained newline-valid and sequential through the latest completed turn after
recovery; no conversation content was deleted. - Before reboot, the patched app-server wrote a valid
token_countrecord at ordinal3588. - After reboot, the official Desktop app-server wrote
thread_settings_appliedat ordinal3588
in the same logical thread. - The SQLite projection then stopped at the duplicate boundary and the UI remained behind the
raw rollout. - Reinstalling or reopening the app did not reconcile the projection automatically.
All identifiers, absolute paths, credentials, and conversation content are intentionally omitted.
Expected behavior
- Desktop should select a deterministic, version-compatible app-server runtime across login,
reboot, and GUI-session reconstruction; a later process must not append duplicate paginated
ordinals to an existing rollout. - On startup and thread open,
thread_history_*should be treated as a rebuildable projection:
detect ordinal/byte-offset mismatches, reconcile it from the canonical rollout, and advance it
to the durable end instead of silently freezing. - If a source rollout truly is missing, recovery should report a precise actionable error and
avoid leaving a ghost/stale thread that appears present but cannot continue. - A follow-up should either be durably persisted and start a response, or return an explicit
dispatch failure; it must not appear successful while leaving the thread unchanged.
Impact
Users see several completed rounds disappear from the visible conversation, cannot continue the
latest turn, and may retry against an old context. This is especially damaging for long-running
tasks because the durable record and the UI disagree without a clear recovery path.
Related reports
- #35746 — paginated history drops valid rollout records and reuses ordinals
- #38792 — desynchronized projection cursors are never repaired on resume
- #40112 — Desktop shows stale pre-crash state after restart while durable history is intact
- #40109 — concurrent rollout writers can assign duplicate paginated ordinals
Please consider a startup reconciliation/doctor path and a regression test that exercises a normal
macOS reboot (or GUI-session rebuild) before and after resuming the same paginated thread.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No implementation files or existing tests are named. Start by tracing app-server runtime selection across restart and the thread_history_* SQLite projection against the canonical rollout; reproduce the duplicate-ordinal resume case. Done means deterministic runtime selection, startup reconciliation to the durable rollout end, actionable missing-rollout errors, and a regression test for reboot or GUI-session rebuild.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, rust, sqlite
- Domain
- backend, databases, desktop
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100