[Desktop][Windows] Paginated thread history stalls on duplicate ordinal while rollout remains complete
Summary
On Windows Codex Desktop, one local paginated thread displayed only an older history snapshot although the canonical rollout JSONL still contained all later messages and the completed task. This was a local history-projection stall, not transcript deletion.
Environment
- OS: Windows 11 x64
- Installed Codex Desktop package: 26.820.9563.0
- Thread-recorded runtime: codex-cli 0.149.0-alpha.4.1
- History mode: paginated
Sanitized evidence
- The rollout JSONL remained parseable and contained exactly one repeated ordinal: ordinal
2186appeared twice. - The two records were
event_msg/token_countandevent_msg/thread_settings_applied. thread_history_projection_stateexpected ordinal2187at the byte offset where the second ordinal-2186 record began.- The projection repeatedly logged an error equivalent to:
expected ordinal 2187, got 2186. - The SQLite projection stopped at an earlier ordinal while later user/assistant records and task completion remained present in the rollout JSONL.
- SQLite integrity checks were clean; there was no evidence of physical database corruption.
- After backing up the files, advancing only the projection byte offset past the duplicate record while keeping the expected ordinal at
2187allowed the projection to catch up. The canonical JSONL was not modified.
Expected behavior
When a paginated history projection encounters a duplicate boundary ordinal, Codex should reconcile or rebuild the projection from the canonical rollout, or safely skip a verified duplicate metadata record. It should not silently leave the UI permanently behind the durable transcript.
Likely cause
This appears related to duplicate ordinal assignment during restart/resume or concurrent app-server writers, combined with a projector that treats a lower ordinal as fatal and has no automatic recovery path. Related reports include #40109 and #40178. Issue #32198 is related to Windows paginated-history handling but appears distinct: it concerns legacy tool_search_output parsing/replay UI freezing, not duplicate ordinals or a frozen SQLite projection.
Requested fixes
- Serialize rollout writers and refresh the durable tail before assigning paginated ordinals.
- Detect byte-offset/ordinal mismatches on startup and rebuild or reconcile
thread_history_*. - Provide a supported history repair/doctor command.
- Surface an actionable error instead of silently showing stale history.
Privacy
No thread ID, absolute paths, prompts, conversation content, credentials, or raw logs are attached.
6 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Additional reproduction on Windows 10 build 19045, package 26.820.9563.0, desktop client 26.820.71523, app-managed backend codex-cli 0.150.0-alpha.8.
Read-only inspection of six affected local tasks confirms the same precise boundary pattern described in this issue: event_msg/token_count followed by event_msg/thread_settings_applied, both carrying the same top-level ordinal. The projection expects the next ordinal and stops updating.
Sanitized samples
Each row is a different task; all task identifiers and conversation content are omitted.
| Sample | Projection expects | token_count ordinal | following thread_settings_applied ordinal |
| --- | ---: | ---: | ---: |
| A | 987 | 986 | 986 |
| B | 639 | 638 | 638 |
| C | 2523 | 2522 | 2522 |
| D | 672 | 671 | 671 |
| E | 368 | 367 | 367 |
| F | 810 | 809 | 809 |
Sample A's persisted projection checkpoint is:
Immediately before that byte offset:
At that byte offset:
These are field-reduced excerpts; other payload fields are intentionally omitted, not empty in the source.
The repeated error is:
Durable data versus visible history
There are also recurring authentication-triggered sign-outs on this machine; separate evidence is being added to #39189. The projection checkpoint had already stalled before the captured sign-outs. A sign-out/restart then makes the UI reload the old cached history, so recent conversation appears to have disappeared despite remaining in the raw rollout. We are not asserting permanent transcript deletion or that authentication caused the duplicate ordinal.
Requested investigation
Please investigate ordinal allocation across the token_count -> thread_settings_applied boundary and provide automatic safe reconciliation, or a supported history repair mechanism, plus an explicit stale-history warning instead of silently showing an old transcript.
We have not applied the manual byte-offset workaround in the opening report, changed affected rollout files, or patched the affected projection checkpoints. An official repair path would be preferable to users guessing which records are safe to skip.
No thread IDs, account information, local paths, prompts, source documents, credentials, raw log archives, or databases are included in this comment.
Confirming this exact defect on a newer Windows hotfix, with an app-wide failure impact.
Environment
26200, x64OpenAI.Codex 26.820.10647.0codex-cli 0.150.0-alpha.8gpt-5.6-solDesktop tasks were resumed/running concurrently atUltrareasoning effortThe package had updated successfully from
26.820.9563.0to26.820.10647.0about 25 minutes before the failure sequence.Exact duplicate boundary
The canonical JSONL remained newline-valid and parseable. Its resume boundary was:
The persisted projection checkpoint pointed exactly at the second
4921record and reported:SQLite structural checks passed, and
codex doctorreported rollout/state-DB inventory parity as healthy. This confirms the current doctor checks do not detect this semantic duplicate-ordinal/projection-cursor condition.App-wide impact
This instance escalated beyond stale visible history:
App server coalesced request queue is fullerrors in about 0.54 seconds, with pending counts around 129-131;codex.exeapp-server exited twice;3221225786/0xC000013A,signal=null, andclassifiedAsExpected=false;ChatGPT stopped unexpectedlyrecovery screen;The affected task is now being kept unloaded to prevent another recovery loop. No rollout, SQLite database, cache, or configuration has been manually altered.
This appears to connect the duplicate-writer/projection defect in this issue and #40109 with the shared app-server failure and queue-saturation families in #35782 and #38385.
Ultraconcurrency is the observed trigger condition here, but the failing component is the local shared app-server/thread-history path, not remote model inference or system resource exhaustion.Requested fixes:
codex doctorto verify ordinal monotonicity and raw-versus-projected terminal-state parity;No thread IDs, task titles, account identifiers, private paths, prompts, project content, raw logs, or databases are included in this report.
Fresh reproduction on a newer Windows Desktop build, with a higher-impact failure mode than stale history alone.
Environment
26.825.3734.0codex-cli 0.150.0-alpha.12.2Sanitized sequence
2026-08-28 04:10:37Z, the rollout appendedevent_msg/token_countwith ordinal166.04:10:53Z,event_msg/thread_settings_appliedwas appended with ordinal166again.thread history projection ... expected ordinal 167, got 1663221225786(0xC000013A) — observed again around04:14:38Z,04:19:52Z, and04:27:21Z.The important additional impact is that this poisoned single thread does not only show stale history: the recurring global app-server restart interrupts active turns in other Desktop tasks as well. One separate task was observed being marked
interruptedduring recovery.A read-only scan of nine recent session rollouts found only the active affected rollout with an ordinal defect (one duplicate, no gaps). The machine had ample free memory and no matching Windows Application Error/Hang or resource-exhaustion event, so this does not look like memory pressure or an OS crash.
The app had recently been reset; this thread and the duplicate were created after that reset, so reset/reinstall is not preventive.
Requested containment
No thread IDs, absolute paths, prompts, conversation content, call IDs, credentials, or raw logs are included here. A local observer is retaining privacy-sensitive incident bundles for private follow-up if maintainers request them.
Follow-up with local mitigation results and a remaining failure mode: the restart loop can be contained, but the originally poisoned thread still cannot display or continue follow-up turns.
Actions performed locally
All changes were preceded by local backups. No canonical rollout JSONL was modified.
166and later448.72.N;N-1;N;1,907,105 -> 1,908,709, expected ordinal remains167.1,586,937 -> 1,588,523, expected ordinal remains73.PRAGMA quick_checkreturnedok.448;3,505,250 -> 3,506,854;449;ok.Outcome
The mitigation partially worked:
73to192.Current sanitized Thread A state:
851and still growing;1,908,709;167;164;55;2;ok.After restart,
thread/resumereturns success but reports only the old interrupted turn andturnCount=2. Newturn/startrequests also return success with no RPC error, and the engine emits reasoning activity for the new turn, but the Desktop history/UI does not advance. To the user, follow-up messages in this thread appear to do nothing.This demonstrates a second containment gap: advancing past a verified duplicate boundary is sufficient for one thread but not enough to recover every already-wedged projection. The durable rollout can continue to append hundreds of valid ordinals while the materialized history remains frozen without surfacing an error.
Requested product fix
rollout latest ordinal >> projection ordinalafter resume and rebuild instead of returning a successful but stalethread/resume.turn/startif the new turn cannot become visible through the thread projection.history repair/reindexcommand and keep one poisoned thread from affecting the shared app-server.No thread IDs, local paths, prompts, conversation content, credentials, or raw logs are included. Backups and incident bundles are retained locally for private follow-up.
Adding one untouched/read-only data point for the
rollout latest ordinal >> projection ordinalcase mentioned above.On another Windows 11 paginated thread using recorded runtime
codex-cli 0.149.0-alpha.4.3, I found exactly one non-monotonic boundary in the entire rollout:The persisted projection cursor expected
20196at exactly the byte offset where the second20195began.The canonical rollout remained valid and continued normally through ordinal
21535, while the history projection remained stuck at that duplicate boundary.No rollout or SQLite repair has been applied; the original stalled state is still preserved for read-only inspection if maintainers need additional sanitized checkpoint/offset metadata.