Repository navigation
Codex paginated rollout can emit duplicate ordinal after unfinished turn, permanently freezing thread history projection #41566
Description
What version of the Codex App are you using (From “About Codex” dialog)?
The latest version as of 29th August 2026
What subscription do you have?
ChatGPT Plus
What platform is your computer?
Windows 10 latest 64 bit enrolled in extended security updates running intel lga1150 platform
What issue are you seeing?
A long-running Codex thread became permanently stuck displaying an old version of its conversation history even though its canonical paginated rollout JSONL continued to receive hundreds of MB of later events.
Forensic inspection shows that the canonical rollout itself contains a duplicate top-level ordinal at the exact byte where thread_history_1.sqlite stops materializing history.
At the first failure boundary:
Physical line 9814
ordinal: 9813
type: token_count
byte end: 143293415
Physical line 9815
ordinal: 9813 <-- duplicate
type: thread_settings_applied
Physical line 9816
ordinal: 9814
type: task_started
The thread-history projection cursor stops exactly after physical line 9814:
next_rollout_ordinal = 9814
rollout byte offset = 143293415
The materializer subsequently reports:
expected ordinal 9814, got 9813
This causes the derived thread history to remain permanently frozen even though the canonical rollout continues.
A second duplicate-ordinal discontinuity was found later in the same rollout at physical line 12831. Both discontinuities have the same observed pattern: an unfinished turn without task_complete, followed by token_count, then a later thread_settings_applied that repeats the preceding ordinal.
Restoring the original thread_history_1.sqlite restores the UI exactly to the stale cutoff. Removing the projection database results in an empty history database; normal startup does not replay the existing paginated rollout into it.
The supported migration classifier was also tested against an isolated copy:
{
"thread_id": "01a03a72-2f06-70b0-a3b8-a309fe1ba833",
"status": "already_paginated",
"bytes_processed": 0,
"message": null
}
Therefore legacy rollout migration does not repair the affected already-paginated thread.
What steps can reproduce the bug?
I do not yet have a safe deterministic minimal reproduction, but both observed failures share this sequence:
Have a paginated Codex thread with an active root turn.
The turn ends abnormally or otherwise remains unfinished without a task_complete event.
The final event associated with the turn includes a token_count.
Later begin another task in the same thread.
In the affected cases, the emitted thread_settings_applied record repeats the preceding record's top-level ordinal instead of incrementing it.
task_started then uses the ordinal that thread_settings_applied should have used.
The history materializer reaches the duplicate and rejects it with expected ordinal N+1, got N.
The canonical rollout continues growing, but the rendered/history projection remains permanently frozen at the last valid record.
I found this pattern twice in the same affected rollout. Normal completed turns immediately before the first failure instead follow:
token_count
→ task_complete
→ thread_settings_applied (next ordinal)
→ task_started (next ordinal)
I have deliberately not attempted to manufacture an unfinished turn by killing Codex because I cannot establish that forced termination is equivalent to the original failure mode.
What is the expected behavior?
Every top-level record in a paginated rollout should receive a unique monotonically increasing ordinal.
Starting a new task after an interrupted or unfinished previous turn should not cause thread_settings_applied to reuse the preceding event's ordinal.
If an incomplete turn is encountered, Codex should either recover/close that turn or otherwise continue writing a valid event stream that the thread-history materializer can consume.
A malformed event should also ideally not make all subsequent valid conversation history permanently inaccessible in the UI.
Additional information
Feedback was also submitted through the Codex app.
Feedback ID: 01a04dc0-1ee7-7b52-9fd9-7a49c827d2f8
Additional forensic observations:
Affected rollout is already history_mode = paginated.
Canonical rollout remained intact and continued well beyond the frozen projection.
First duplicate occurs immediately after the projection's final accepted byte.
A second duplicate ordinal occurs later in the same rollout with the same unfinished-turn transition pattern.
Three normal completed turns immediately preceding the first failure contain task_complete and have consecutive ordinals.
thread_history_1.sqlite accurately represents history only through the last valid ordinal before the discontinuity.
Removing the history projection DB causes Codex to create an empty replacement rather than replaying the existing paginated rollout.
codex migrate-rollouts --json --thread on an isolated copy returns already_paginated with bytes_processed: 0.
I have preserved the original affected rollout and projection databases and can provide additional sanitized logs, exact event windows, byte offsets, or database state if useful.
No canonical rollout data was modified during diagnosis.
Activity
github-actions commentedon Aug 29, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
SuperReaper1999 commentedon Aug 29, 2026
Related to issue #41079 possibly and issue #41353 appears to describe the same underlying ordinal-writer failure class. My affected rollout provides an additional concrete instance where thread_settings_applied repeats the preceding token_count ordinal, permanently wedging history materialization. I also found a second duplicate-ordinal transition later in the same rollout. The missing task_complete correlation may be incidental to the broader stale/competing-writer mechanism described there.
mikezio commentedon Aug 29, 2026
Additional confirmed instance on macOS Desktop with iOS Remote symptoms.
Environment:
26.825.416510.151.0-alpha.7.1; standalone CLI used for verification:0.151.0User-visible impact:
thread-store internal error: thread history projection expected ordinal 4516, got 4515.Forensics:
4515; the duplicate record wasthread_settings_appliedat a resume boundary.4516at the byte offset where the second4515appeared, so materialization could not advance even though the canonical rollout continued.Verified recovery (after preserving byte-for-byte backups):
0..5280, 5,281 ordinal-bearing records, zero anomalies).After that repair, the same-directory fork succeeded and the repaired child thread completed a validation turn normally. The original affected thread was archived rather than deleted. A post-restart
codex doctorrun reported 22 checks OK, 0 warnings, and 0 failures.This case supports the same underlying failure described here: a resumed writer can reuse the preceding ordinal, and the materializer does not self-heal. It also shows that the resulting local projection failure can surface to users as an apparent macOS/iOS Remote sync problem. Ideally ordinal allocation should be serialized and existing malformed projections should be detected and rebuilt or repaired without requiring direct rollout/database intervention.
I retained the original rollout and pre-repair projection database locally and can provide a narrowly sanitized event window or checksums if maintainers need them.
4Liberty commentedon Aug 30, 2026
Codex paginated-history producer and self-healing projection defect
Sanitized evidence
This report contains aggregate structure only. It excludes thread identifiers, prompts,
conversation content, local paths, credentials, and raw logs.
0.151.0-alpha.7.1.token_count(N)/task_started(N)pairs and2 duplicated no-op
thread_settings_applied(N)records.migration-rewritten canonical EOF.
expected ordinal 1073, got 946.The failure is not renderer-only. The history projector stops at the last valid SQLite
prefix and later reads keep returning that prefix even though the canonical rollout grows.
Tested reference patch
The attached patch applies to
openai/codexmain commit63d213884daea50e4f74efc192cdc44f549b67d5.It implements these invariants:
not a stale inode, and recomputes its ordinal allocator from the last complete durable
record before retrying buffered items.
lifecycle writes. An unloaded thread additionally uses the writer coordinator.
out of range, the projector parses the complete canonical rollout before touching SQLite.
immediately preceding history-no-op
token_count(N)projection step with the meaningfuladjacent
task_started(N)record.incomplete durable tails remain fatal.
transaction. Readers keep the old readable prefix until commit; any error rolls back.
Regression results
codex-rollout: writer reopen recomputes ordinal state from the durable tail — passed.codex-thread-store: duplicate token-count/task-start strict rebuild — passed.codex-thread-store: stale cursor rebuild is atomic and malformed canonical historypreserves the old prefix — passed.
cargo fmt --all -- --check— passed (stable rustfmt only emitted the repository'sexisting nightly-option warnings).
App-server and renderer integration design
The thread store should return a typed projection outcome rather than only logging:
up_to_daterepaired { old_cursor, new_cursor }unrecoverable { cursor, canonical_fault_class }On
repaired, the app server should invalidate the thread-history cache and emit athread-scoped
history/projectionRepairednotification. The desktop client should refetchthe affected thread/turn list while preserving selection and scroll anchoring.
On
unrecoverable, list/read responses must carry a visible degraded-history status. Thedesktop client should render a persistent error affordance with a retry action rather than
silently displaying the last valid prefix as if it were current. No automatic path may skip
meaningful conflicts.
Materialization should run on append/flush and as a bounded read-path preflight whenever a
stored cursor is not an exact canonical record boundary or EOF. Successful rebuild must be
committed before the repaired notification is emitted.
Release acceptance
A signed release is complete only when it:
fixtures;
failed to project durable rolloutwarnings in a fresh follow-up cycle.Until then, local derived-state repair is mitigation only; upstream remains pending.
alexandrusavin commentedon Aug 31, 2026
Disclosure: this comment was generated by Codex from local diagnostics and posted with the user's explicit approval. It contains no prompt/conversation content, credentials, local paths, or thread identifier.
Another confirmed macOS instance, on a slightly newer signed desktop runtime:
26.825.515110.151.0-alpha.7.226.6.2build25G83, Apple Silicon (arm64)User-visible impact:
thread-store internal error: thread history projection ... expected ordinal 1256, got 1255.Forensics:
1255,token_count1255, duplicatethread_settings_applied1256,task_startedthread_history_projection_statestopped at byte offset9542592, expected ordinal1256; that offset was exactly the end of the last valid line and start of the duplicate.already_paginated,bytes_processed: 0.Verified local recovery, after preserving the rollout, projection database, and exact malformed line:
9542592to9545643, keeping expected ordinal1256, thereby skipping the duplicate metadata line.This was a narrowly targeted, backed-up local recovery, not a recommendation for an unsupported end-user repair flow. The case independently confirms the same
token_count(N) -> thread_settings_applied(N) -> task_started(N+1)producer defect on macOS and shows that a no-op duplicate can be skipped while preserving later offsets. The upstream fix should still prevent duplicate allocation and make the projection self-heal.Jiaming-Zhu commentedon Aug 31, 2026
I can confirm the same failure on Linux x86_64. The affected thread was created with Codex CLI 0.149.1 and diagnosed/recovered with 0.151.0.
The raw rollout remained valid JSON and contained 51,450 lines (537,124,417 bytes), but had exactly one duplicated top-level ordinal at zero-based physical line 2,379:
token_count, ordinal 2,378thread_settings_applied, ordinal 2,378 (duplicate)task_started, ordinal 2,379The projection state stopped at ordinal 2,379 and byte offset 5,165,166, exactly where the duplicate began. Logs repeatedly reported
expected ordinal 2379, got 2378. The raw rollout continued growing, but 49,071 subsequent lines were inaccessible through thread history.migrate-rolloutsreportedalready_paginatedand processed zero bytes.Recovery was verified after stopping the active writer and backing up the rollout and databases:
The projection then advanced from 2,379 to 51,450 lines, from 3 to 111 turns, and from 735 to 16,571 projected items. JSON parsing, ordinal validation, and SQLite
quick_checkall passed afterward.This confirms the issue is cross-platform and can occur on the CLI path. The content was not deleted; a single duplicated ordinal permanently froze projection at a resume boundary.
No thread identifiers, local paths, or conversation content are included here. This diagnostic comment was prepared by Codex and is being posted with the user’s explicit approval.
YDLuo-1 commentedon Sep 1, 2026
I have an independent Windows reproduction of the same failure mode, with one useful variation: the duplicated second record is
task_started, notthread_settings_applied.Environment:
codex-cli 0.151.0-alpha.7.2history_mode = paginatedSanitized rollout audit:
The failure boundary is:
The Desktop log reports:
The UI/history projection remains permanently at the earlier boundary, while the canonical rollout continues with valid later messages and eventually reaches
task_complete. Restarting and reopening the thread does not make the projection catch up.The user logged out/switched account and later reopened the task during the multi-hour gap. That is correlation, not proof that account switching is the root cause. The stronger evidence is that a resumed/new task writer reused the final durable ordinal after a long interruption.
This broadens the suspected writer bug beyond
thread_settings_applied: ordinal initialization/allocation during resume or restart may be shared across multiple event types, includingtask_started.Suggested regression case:
For prevention, the resumed writer should determine its next ordinal from the locked durable rollout tail rather than stale in-memory state. For existing affected rollouts, a supported local repair/reindex path should recover the projection without requiring users to edit the canonical JSONL.
This also closely matches #41079. I have retained the original rollout and projection databases, but have deliberately not posted the thread ID, local paths, prompts, tool output, credentials, or raw transcript. I can provide additional sanitized ordinal/type/timestamp windows if maintainers need them.
cappallo commentedon Sep 1, 2026
Additional confirmed occurrence with the same boundary pattern.
Environment:
Sanitized failure boundary:
The live task continued successfully in memory for roughly 23 more hours and the canonical rollout reached ordinal 9687, with all later messages intact. Restarting Codex Desktop did not create the malformed record; it exposed the existing projection stall when history was reconstructed. The parent task then rendered only the stale prefix, while direct navigation to the continuation segment produced “no rollout found for thread id …”.
codex migrate-rollouts --thread ... --json --verboseclassified both segments asalready_paginatedand did not repair them.Full local backups were preserved. Recovery is using the safer workaround documented in #41079: advance only the derived projection cursor past the duplicate metadata record, leaving the canonical rollout unchanged.
No prompts, thread IDs, absolute paths, credentials, or raw logs are included here.
hajimeno-ipoo commentedon Sep 1, 2026
Additional confirmed occurrence on macOS
I can confirm the same duplicate-ordinal and frozen-projection failure pattern on macOS.
Environment:
history_mode = paginatedObserved evidence:
next_rollout_byte_offset = 82,436,928withnext_rollout_ordinal = 17061.ordinal = 17060begins at exactly byte 82,436,928.17060:event_msg/token_count17060:event_msg/thread_settings_applied17061:event_msg/task_startedinProgress; later valid events continued in the canonical rollout but were never materialized intothread_history_1.sqliteor shown in the Desktop UI.Preceding lifecycle evidence:
EPIPE, and the app-server transport stopped at 08:05:07Z.interrupted.thread_settings_appliedordinal.An
account/logoutfollowed byaccount/login/startoccurred about 55 minutes earlier and also caused an app-server IPC reset. This may be a contributing lifecycle condition, but the available evidence does not establish that the account switch directly caused the later duplicate ordinal.No canonical rollout data, projection database, or application files were modified during diagnosis. I can provide sanitized exact event windows, byte offsets, or relevant lifecycle log excerpts if useful. Raw rollout files are not being uploaded because they contain private prompts, source code, and local paths.
xhplyf618 commentedon Sep 2, 2026
Summary
On Windows, multiple local Codex threads showed older, incomplete conversation state after the app was restarted or after a thread was reopened. Completed assistant responses had previously been visible, but the UI later displayed an earlier partial response or an apparently unfinished turn.
Read-only inspection found two distinct failure modes:
ordinalin the canonical paginated rollout. Subsequent events remain in the JSONL, but the rendered/history view stops at an older boundary.latestTurnStatus=completedandmarkedStreaming=true. These threads can still visually roll back to an older state.The issue was first observed after reopening the app on 2026-09-01 and recurred across several threads on 2026-09-02.
Environment
OpenAI.Codex26.825.6671.0x64codex-cli 0.149.110.0.26200, build26200, 64-bitzh-CNCODEX_SPARKLE_ENABLED=falseat both User and Machine scopes26.825.6671.0; no version transition was observedFailure mode A: duplicate ordinal followed by stale/frozen history
Two originally affected long-running threads retained later raw events, but each contained one duplicate top-level ordinal at a transition from
token_counttothread_settings_applied.Sanitized evidence:
When these threads were reopened, the desktop log reconstructed them as interrupted and still streaming:
The final assistant content and later rollout events were still present in the canonical JSONL. No canonical rollout data or history database was modified during diagnosis.
Failure mode B: completed turn is still marked as streaming without ordinal corruption
Two newer continuation threads were checked separately:
Despite the valid ordinal sequence, the desktop app logged completed turns as still streaming:
The same thread could therefore have an intact completed turn in its raw transcript while the reopened UI showed an older partial state. This suggests a stale resume/rehydration state that is independent of duplicate ordinal corruption.
Observed sequence
This is not yet a deterministic minimal reproduction, but the observed sequence was:
Expected behavior
Actual impact
Recovery attempts and checks
Possibly related public issues
Questions for the Codex team
26.825.6671.0for stale thread rehydration or completed turns being marked as streaming?latestTurnStatus=completedwithmarkedStreaming=trueinstead of allowing the older streaming state to win?maybe_resume_successevents help?Privacy note
This report intentionally excludes names, project titles, prompt/response content, filesystem paths, credentials, full conversation IDs, and full raw logs. Additional evidence can be provided after a separate privacy review.
offx366 commentedon Sep 2, 2026
I reproduced this failure on Linux with two independent affected threads and prepared a minimal tested producer fix:
offx366@55e916e298
Observed failure boundary in both cases:
Root cause: resume-tail discovery uses
ReverseJsonlScanner::scan_next::<RolloutLine>(). Withserde_json/arbitrary_precision, direct deserialization can reject the flattenedtoken_countfloat record, so the scanner falls back to the preceding ordinal and the resumed writer reusesN. Thread-history projection then freezes at the duplicate.The patch scans into
serde_json::Valueand calls the existingdecode_rollout_line, matching the projector decoder. The regression test appends a float-bearingtoken_count@5, resumes, and asserts the next record is ordinal 6.Verification:
[0, 4, 5, 5][0, 4, 5, 6]just test -p codex-rollout: 126/126 passedjust fix -p codex-rollout: passedcargo fmt --all -- --check: passedI attempted to open an upstream PR from
offx366:fix/rollout-ordinal-decoder, but this repository restrictsCreatePullRequestfor external accounts. Maintainers can cherry-pick55e916e298or enable/invite a PR. This patch prevents the decoder-induced producer defect; self-healing of already damaged projections remains separate.7 remaining items
prodan1234 commentedon Sep 7, 2026
Additional macOS confirmation from read-only diagnostics on 2026-09-07 UTC. This report contains structural metadata and aggregate counts only; no private task IDs, local paths, prompts, or conversation content are included.
Environment:
26.901.51231(build8109).codex-cli 0.153.4, verified from the executable in the app bundle.The failure persists across app-server restarts. Retained telemetry contains four affected threads and 2,161 instances of the projection warning. One unarchived task with recent activity accounts for 1,062 warnings across ten app-server processes, from September 5 05:09:38 UTC through September 7 06:38:21 UTC.
For the active case, the projection checkpoint is byte
415234111, expected ordinal41431. The durable rollout has continued to byte606095396, ending at ordinal64618and atask_completerecord at September 7 06:38:21.391 UTC. The exact boundary is:A streaming validation of the entire 190,861,285-byte suffix after the frozen checkpoint found:
thread_settings_applied(ordinals41430and41483); no forward ordinal gaps.task_startedand 157task_completerecords after the frozen checkpoint.This establishes a valid-JSON but discontinuous ordinal stream and a stale derived index while later history remains durable. It does not establish the exact writer race or parser behavior that originally caused the ordinal reuse.
There is already an upstream materialization fix, but it has not reached the stable runtime examined here:
rust-v0.153.4,thread_history_materialization.rs:193–198returns an error forordinal < next_ordinal.095ac4f131e759b204fa6368dc42d2feff6eb21a, adds recovery past duplicate/regressed records and anomaly telemetry.rust-v0.154.0-alpha.3,thread_history_materialization.rs:206–219contains that duplicate-skipping behavior; the alpha source was inspected, not installed.Could the existing fix be backported to the stable runtime and shipped in the production Desktop app? Please also retain regression coverage for a resumed thread with a trailing
token_count(N)followed bythread_settings_applied(N), including two such discontinuities in one durable suffix.The intended supported recovery is for a production build containing the fix to catch up from the existing projection checkpoint through normal materialization, then verify that the checkpoint reaches the complete durable suffix and recent history becomes available. This local recovery has not been executed or claimed verified: the affected rollouts, databases, and app runtime were left unchanged. No alpha build or manual database/rollout repair was used.
rocoking331-netizen commentedon Sep 7, 2026
I can reproduce this exact issue on Windows with Codex Desktop package
26.901.6511.0_x64(runtime0.150.1).Observed evidence:
thread history projection ... expected ordinal 289, got 288.event_msg/thread_settings_applied; the next valid record used ordinal 289.User impact:
The conversation appeared to lose both recent and older work after restarting the app, and substantial additional Codex usage was consumed diagnosing and recovering from this product defect.
I attempted the in-app
feedback/uploadroute twice with a sanitized diagnostic report and no transcript attachment, but both attempts timed out while connecting to the Sentry ingestion endpoint, so I am adding the reproduction here.Compensation request:
Please grant two Codex usage-reset credits for the usage consumed by this incident, after account verification. Because account/session identifiers should not be posted publicly, please advise the official secure support channel where I can provide those details privately.
No thesis/PPT content, raw conversation text, account identifier, thread identifier, or local filesystem paths are included in this comment.
argszero commentedon Sep 7, 2026
Consolidated status for this thread (the mechanism, the fix state on
main, and the one question several of you have asked: is the fix in a stable release yet?).Mechanism (consolidated from the 15+ reports here and the satellite issues)
The producer defect is a resumed writer reusing the final durable ordinal after an interruption. On builds before #42378, resume-tail discovery ran the backward scan through
ReverseJsonlScanner::scan_next::<RolloutLine>(); withserde_json's arbitrary-precision handling, direct deserialization bails on the trailing float-bearingtoken_countrecords (decimalrate_limits.used_percent), so the scanner falls back k records and derives a stale next ordinal (N−k, k = trailing decimal-bearing records). The first post-resume append — usuallythread_settings_applied(written via the raw settings-restore path, i.e. the natural first writer after a fresh-process resume), sometimestask_started— then reuses N. The projector parks exactly there:expected ordinal N+1, got N.This matches every boundary in this thread:
token_count(N) → thread_settings_applied(N) dup → task_started(N+1), with the one-trailing and two-trailingtoken_countvariants (unravel11's cases B/E, prodan1234's second discontinuity, #43142's k=3 evidence) and thetask_started(N)duplicate variant (YDLuo-1, woshishinidie). It was independently root-caused and patched by offx366's55e916e298(scan intoserde_json::Value, decode viadecode_rollout_line) — the same shape that landed upstream as #42378.Fix state on
main(verified against current tags)69cebb5d15, merged Sep 2): rollout reads routed through the canonical decoder → a resumed writer no longer mis-derives the ordinal → no new duplicate/regressed ordinals.095ac4f131, merged Sep 2): the batch materializer now skipsordinal < next_ordinallines with a recordedDuplicateOrRegressedOrdinalanomaly and advances the cursor (thread_history_materialization.rs:206-219on main) → an already-stalled projection catches up on the next open/resume once running a build with this fix. prodan1234's source comparison ofrust-v0.153.4vsrust-v0.154.0-alpha.3is exactly right.Is it in a stable release? Not yet. Tag ancestry as of 2026-09-07: stable line ends at
rust-v0.153.4(published Sep 4) and contains neither fix (verified viagit rev-list rust-v0.153.4); the newest build containing both isrust-v0.154.0-alpha.3. There is norust-v0.154.0stable and no 0.153.x patch with the backport yet — so for users on the stable desktop bundle, the two options are the alpha line (where #43262 empirically showed a stalled 608MB thread fully recover: 27,857 items / 42 turns reprojected) or waiting for a stable release/backport decision.What still needs maintainers (the remaining open work)
migrate-rollouts --applyreturnsalready_paginatedwhenhistory_mode == Paginatedwithout checking projection consistency (rollout_migration.rs:513-517), so there is no non-destructive recovery command; the strictapply_projectionpath still hard-errors and bricksthread/forkandthread/reverton a stale cursor (ArthurOstapenko's fork-32603, cappallo's segment failures, YDLuo-1's frozen fork). 4Liberty's reference patch (Aug 30, tested against63d213884d) remains the fullest published design for this: strict rebuild that consumes a duplicated no-op settings record, atomic replacement of only the affected thread's derived rows, and typed projection outcomes (repaired/unrecoverable) surfaced to the client.token_countrecords plus internal-history segments (unravel11/prodan1234), and the resumed-writer test shape YDLuo-1 suggested (persist token_count@N; interrupt; resume; assert next ordinal == N+1) — upstream Route rollout reads through the canonical JSON decoder #42378's regression test covers k=1 only.Family map for triage
This thread is the canonical issue. Same mechanism, same pre-fix runtimes: #43124 (macOS), #43182 (macOS, 0.153.4), #43142 (Windows), #43262 (Windows recovery proof), #43451 (macOS, filed today), and earlier #42999 / #42157 / #42241 / #41986; adjacent writer-serialization issues #40109 / #41079 / #41353; stale-rehydration-without-ordinal-corruption #39885. A single fix release + a repair path would close the whole cluster.
No transcript content or identifiers from any affected thread are referenced above; all claims are from the sanitized structural reports in this thread and public source/tag inspection.
PracticalSwan commentedon Sep 7, 2026
Current Windows reproduction on the latest signed Desktop/runtime available on this machine (sanitized; no transcript content, credentials, local paths, or thread identifier):
26.901.6511.00.153.4The latest active conversation hit the same producer/projection failure during a normal later turn start after an earlier completed segment. Read-only rollout metadata at the failure boundary is:
The durable history projector then repeatedly logged:
Read-only projection state confirms the cursor is parked exactly at the duplicate
task_startedrecord:That byte offset is exactly the start of the second ordinal-1074 record. The canonical rollout remains valid JSON and continues beyond the duplicate.
thread_history_1.sqlitereturnsPRAGMA quick_check = ok, so this is again a logical writer/projection inconsistency rather than structural SQLite corruption.This reproduction is useful because the duplicate record is
task_started, notthread_settings_applied, and it occurs on shipped0.153.4, confirming the writer-side ordinal reuse remains possible in that signed runtime. No repair/database mutation has been attempted in this diagnostic pass.Gonzo15918 commentedon Sep 8, 2026
I can corroborate this exact failure signature on Linux with
codex-cli 0.153.4.It occurred in two independent long-running local desktop tasks, including a replacement
task created after the first task became unusable through Remote.
For the most recent occurrence:
The duplicate above was the rollout's only non-monotonic event. The task-history API
returned the older turn as
inProgress, and Remote repeatedly showed an old commentaryas the latest update even though the rollout continued normally.
I also tested recovery on this affected task. After making a transactionally consistent
backup of
thread_history_1.sqlite, I atomically advanced only this task's projectioncursor from the duplicate non-message record to the immediately following expected
ordinal-3373
task_startedrecord:I did not rewrite, delete, or renumber any rollout record. The projector immediately
caught up to the live end without an app restart. A later verification showed:
This is not a recommendation that users edit SQLite manually; it is additional
localization evidence that the canonical rollout is intact and that the permanent
failure is caused by the projector being unable to reconcile the duplicated non-message
ordinal. A supported repair path could safely recognize this exact metadata pattern,
preserve all message records, and resume at the next expected ordinal.
Environment:
I can provide a further-redacted event window and projection metadata if useful. I am
not attaching the raw rollout or database because they contain private conversation and
workspace data.
adolphinvx commentedon Sep 8, 2026
Additional corroboration from a local macOS desktop task (sanitized):
0.153.4thread/forkand receives error-32603:The failure reproduces across multiple Side Chat attempts. Configuration loaded normally; no raw transcript, task identifier, project path, credentials, or logs are included. This is additional evidence that an ordinal/projection inconsistency blocks the fork-based Side Chat flow for already-affected local tasks.
czakian commentedon Sep 8, 2026
Additional confirmed occurrence on Linux with Codex CLI/app-server 0.153.4. User-confirmed trigger: the host ran out of memory, and the user rebooted it while the affected session was still running. The session was subsequently resumed. This appeared to the user as a remote connection failing to update an existing session. The duplicate record in this case is
task_started.Environment and impact
7.0.0-31-generic, x86_64.codex app-server --remote-control --listen unix://.history_mode = paginated.thread/resumerequest. The durable rollout contained newer completed turns, but the history projection remained at an older turn.Exact failure boundary
Sanitized top-level event metadata, with zero-based physical record positions:
The systemd service started after the host reboot at 03:07:37 UTC, between the two ordinal-2474 records. Every subsequent ordinal is one behind its physical record position.
Repeated log from
codex_thread_store::local::live_writer:Projection state at diagnosis:
There are 671 records after the projection cutoff, including completed turns through 03:53:47 UTC. The last indexed turn remained
inProgressin the live projection database.Controlled recovery test
We preserved the original rollout and tested separate, isolated copies of the state/history databases with the same 0.153.4 binary:
thread/resume, followed bythread/turns/list, still returned the older history. Projection remained at ordinal 2475 / byte 12825091.thread/resume, the projection advanced to ordinal 3146 / byte 15329346, andthread/turns/listreturned the latest three completed turns.No projection rows were manually removed or edited in this test, and no model turn was started. The live rollout has not been modified.
This isolates the stale remote history to the ordinal/projection failure. The out-of-memory condition and reboot during the running session are user-reported; the reboot/resume event boundary is corroborated by local timestamps. We have not established whether the kernel OOM killer terminated a Codex process before reboot. This is not a deterministic minimal reproduction or proof of the precise writer-side cause. A supported recovery path and release guidance for affected 0.153.4 sessions would be helpful.
This report includes structural metadata only; private conversation contents, credentials, local paths, and thread identifiers are omitted.
Martin9204 commentedon Sep 8, 2026
Additional confirmed macOS instance, with a controlled prerelease comparison and a completed, user-verified recovery on September 8, 2026.
This report was prepared with Codex and posted with the affected user's permission. It contains structural evidence only; no conversation text, task identifiers, project names, local paths, credentials, databases, or raw logs are attached.
Environment and failure
26.901.51231, build8109, bundle identifiercom.openai.codex.0.153.4, rechecked after recovery.event_msg/thread_settings_applied. The projection checkpoint stopped exactly at that discontinuity, withcodex_thread_store::local::live_writerreportingexpected ordinal N, got N-1. Later user and assistant messages were still in the canonical transcripts.Controlled copy tests
Testing used fresh copies of the state/history databases and complete-record transcript snapshots in network-disabled Docker containers, with the official
@openai/codexpackages. No credentials were copied and no successful model request was made.0.153.4, affected unmodified snapshots0.153.4already_paginated0.154.0-alpha.6, unmodified transcript copies, resume only0.153.40.154.0-alpha.6, including restart and another synthetic messageRecurrence on stable was demonstrated separately: after prerelease-assisted recovery of three copied threads, submitting one synthetic message per copy using
0.153.4caused one thread to stall again. Its captured pre-resume tail was a token-count event. The projector logged ten instances ofexpected ordinal 38553, got 38552; the new message was not projected. The other two copies persisted their messages. The driver exit code alone did not detect this failure; database inspection did.These are controlled tests using affected snapshots, not a minimal reproduction from an empty installation or proof that all recurrence mechanisms are fixed.
Completed recovery and native Desktop confirmation
With Desktop and all other live-history holders closed, fresh backups were taken. The prerelease rebuilt only disposable copies; after verification, the four allowlisted threads' derived rows were imported in one guarded SQLite transaction. No canonical transcript, state database, application binary, or unrelated task was replaced or edited by the recovery.
All four final checks passed:
0.153.4The final live report recorded
applied: trueandverified: true: 4,431 original visible messages matched by ID and text, all four checkpoints reached the captured transcript ends, transcript sizes/SHA-256 hashes were unchanged, unrelated rows and migration records matched the fresh backup, and SQLite integrity checks passed. After reopening Desktop, the user confirmed that the previously missing messages were visible.This is recovery evidence, not a recommendation to edit databases or a permanent fix for
0.153.4.Release guidance requested
The public fixes #42369 and #42378 were merged on September 2. Both merge commits are ancestors of
rust-v0.154.0-alpha.6and are not ancestors ofrust-v0.153.4. The stable tag's materializer still errors on a regressed ordinal, and its ordinal reader still uses the directRolloutLinescanner. The latest stable GitHub release checked for this report remains0.153.4.Please clarify the first supported Desktop/stable build shipping both changes, whether already-stalled histories recover automatically after upgrading, and whether a supported per-thread integrity/recovery operation will be available. The successful prerelease tests do not establish the exact initiating cause for these four original failures or certify all prerelease behavior.
cookerpapa commentedon Sep 9, 2026
Deterministic Windows reproduction:
0.0versus0, without a crash or model callI reproduced the producer defect through the public app-server API with a five-record synthetic paginated rollout. This supplies a small deterministic trigger for this issue: a forced interruption, concurrent writer, long conversation, or model request is not needed for this reproduction.
Tested on Windows 11 x64, build 26200, on September 9, 2026:
OpenAI.Codex 26.901.6511.0.codex-cli 0.153.4, checked with--version. The older CLI version recorded when a thread was created is not used as the current runtime version.@openai/codex@0.154.0-alpha.8-win32-x64; package SHA-512 integrity checked and executable version verified. This was installed only in a separate test directory.Producer reproduction
Create a fresh isolated
CODEX_HOME, an offline local model-provider configuration, and a newline-terminated JSONL fixture containing these records:Then call
initializewithexperimentalApi: true,initialized,thread/resumewith the fixture path andexcludeTurns: true, andthread/settings/updatewitheffort: "high". Close the app-server normally through stdin EOF. Noturn/startrequest is sent.0.153.40.00,1,2,3,4,4expected ordinal 5, got 40.153.400,1,2,3,4,50.154.0-alpha.80.00,1,2,3,4,5,6The last record is serialized as a decimal in the first and third cases, and as an integer in the control. Each run uses a separate home. The stable binary itself writes the duplicate
thread_settings_applied; the fixture does not contain a duplicate. The preceding synthetic turn is explicitly completed.All three public RPCs (
thread/resume,thread/settings/update,thread/turns/list) report success in the failing stable case. Detecting the failure requires inspecting the persisted ordinal sequence/checkpoint or the warning, not just the RPC status.Recovery comparison
In a separate test, I retained the duplicate produced by
0.153.4, closed the server, and appended three synthetic records with ordinals5,6,7representing a second completed turn. Two disposable homes received byte-identical rollout copies and equivalent copies of the frozen projection state; only the state database's local rollout path was adjusted for each home.0.153.40.154.0-alpha.80.153.4, without updating settings or starting a turnAlpha appended a settings record at ordinal 8. The entire pre-existing 3174-byte canonical prefix remained byte-identical, verified by SHA-256; no duplicate or message record was edited, renumbered, or deleted. SQLite
quick_checkreturnedok. This last stable read verifies persistence only; it does not establish that further writes on stable cannot reproduce the defect.Root cause and existing fixes
The decimal/integer control supports the decoder mechanism already discussed here and addressed by #42378. In
rust-v0.153.4ordinal discovery, the reverse scanner directly deserializesRolloutLineand ignores rejected records. Rejection of the float-bearing final record lets it derive the next ordinal from the earlier record. The subsequent settings append therefore reuses the final durable ordinal. This is consistent with the flattened-envelope/nested-decimal decoding problem described and fixed by #42378.The second failure is explicit in the stable materializer: a regressed ordinal returns an error and prevents later valid history from being projected. #42369 adds recovery past that boundary. Both fixes were already merged; I am reporting controlled binary verification, not proposing those patches as new work.
The affected real desktop task has the same structural boundary,
token_count(38691) -> thread_settings_applied(38691) -> task_started(38692), exactly at the frozen projection byte offset. Its later conversation records remained valid JSON on disk. No real conversation content, task identifiers, local paths, credentials, or raw logs are included here.As of this check, npm's
latesttag still resolves to0.153.4. Could the applicable prevention and recovery fixes be shipped/backported to the stable desktop runtime, and the first stable desktop build containing both be identified?Prepared and tested with Codex, and posted with the affected account owner's authorization. The actual desktop task and its databases were not modified by these reproduction tests.
Self-contained Python reproducer (standard library; tested on the binaries above)
Save as
reproduce_history_ordinal.pyand run each case against a fresh disposable home:The script creates a new isolated home under the supplied work directory, uses a local non-authenticated dummy provider, disables hooks and analytics, and makes no model call. It prints the persisted ordinals and checkpoint. It does not open the normal application data directory. The recovery comparison above was a separate experiment; this script reproduces the producer/control cases.
ChuLaiTheGreat commentedon Sep 9, 2026
Disclosure: this comment was prepared by Codex from local structural diagnostics and is being posted with the affected account owner's explicit approval. It contains no task/thread identifier, project name, prompt, conversation content, credential, private path, or raw log.
Additional current confirmation on the stable
0.153.4runtime, plus a narrowly validated recovery result.Environment and topology:
26.901.51231(build8109)0.153.4The frozen boundary was structurally identical to the producer defect consolidated above:
The projection cursor was parked at byte
34332222, expecting ordinal910, exactly where the second ordinal909began. The canonical rollout remained valid and grew to62557748bytes, leaving28225526bytes and nine latertask_completeevents unprojected.thread/readexposed only the old ten-turn prefix. SQLitequick_checkwasok, andcodex doctorreported database integrity/inventory status without detecting this logical cursor mismatch.A separate isolated copy of an earlier occurrence remained frozen on
0.153.4after successful-lookingthread/readandthread/resume;migrate-rolloutsreturnedalready_paginatedand did not repair it.Verified recovery, after consistent SQLite/rollout backups and confirmation that no task scope or App Server writer was active:
next_rollout_byte_offsetby the duplicated record's exact 1,555-byte length.next_rollout_ordinalat910.The projector then consumed the remaining valid records and reached exact EOF at
62557748 / 2099.quick_checkremainedok, and the API-visible history increased from 10 to 20 turns, including the previously hidden recent completed work.This corroborates that stable
0.153.4still has both the producer and recovery gap. It also validates the core behavior expected from #42378 and #42369: prevent the duplicate on resume, and skip/reconcile the already-persisted regressed metadata record so an existing projection can catch up without source-rollout mutation. A supported per-thread repair/doctor path is still important for users who cannot safely perform internal SQLite surgery.rdleclerc commentedon Sep 10, 2026
Additional macOS occurrence: history still frozen after desktop update
Prepared with Codex and posted at the affected account owner's explicit request. This report contains structural diagnostics only. It excludes conversation text, company and project names, contact information, task identifiers, private filesystem paths, credentials, databases, and raw logs.
Environment
--version.User-visible impact
An existing long-running local task repeatedly reopens at an old assistant message from September 3. Messages and work from the following days disappear from the rendered history. The raw session JSONL still contains later user messages through September 10, including the current complaint. Before the update, the task-history reader independently returned the September 3 turn as its newest turn even while task metadata was current.
The update did not recover this task: the same projection checkpoint and the same live error were reverified afterward. This is persistent apparent history loss, not evidence that the later transcript was deleted.
Exact failure boundary
Sanitized metadata from consecutive records in the affected canonical JSONL:
event_msg/token_countevent_msg/thread_settings_appliedevent_msg/task_startedThese are two distinct records with the same ordinal, not a duplicated display of one record.
Read-only inspection of
thread_history_1.sqliteafter the update showed:At 2026-09-10 08:54:38 Pacific, the canonical rollout was 1,082,234,375 bytes and still being appended to, far beyond that frozen checkpoint.
Live warnings from
codex_thread_store::local::live_writercontinued after the update, including at 08:54:33 and 08:54:38 Pacific:Reproduction scope and unknowns
The observed user path is to continue the affected task, reopen it or update/restart the desktop app, and see the old history again. The persisted duplicate boundary and blocked projection are confirmed. The original action that created the duplicate ordinal has not been established; this report does not claim a deterministic producer reproduction, a concurrency cause, or a conversation-size cause.
No transcript renumbering, record deletion, history-database clearing, migration, or prerelease recovery has been attempted during this diagnosis. No full session or raw log was uploaded.
Requested resolution
Please address both creation of duplicate ordinals and safe recovery of already-affected tasks. Updating the desktop app alone has not repaired this instance. A recovery path needs to preserve both distinct records and all later turns, make the history reader catch up, and keep history current after reopening. Until then, the app should make the stalled projection visible rather than presenting an old turn as current history without an actionable warning.
Local deduplication marker:
history-projection-20260910-5739-5738.Jok98 commentedon Sep 10, 2026
Additional confirmation on Linux: two local paginated threads show the same duplicate-ordinal failure as this issue.
Environment
26.901.20858.0.153.0-alpha.5.7.1.9-arch1-2, Hyprland/Wayland. The Linux Debian package was converted to an Arch package; this is outside the officially supported distributions.26.903.71938has not been tested.Observed failure
After a forced reboot during ongoing work, both conversation histories remained at their earlier cutoff even though their canonical JSONL files kept receiving later turns.
The failure boundaries match the pattern reported here:
The app logs repeatedly report this error for Thread A (identifier redacted):
All original JSONL records parsed successfully.
quick_checkpassed for both the state and history databases. The checkpoint is immediately before the repeated ordinal. The association with the reboot is observed; I have not constructed a deterministic reproduction of the initiating writer failure.In both captured boundaries, the preceding
token_counthasrate_limits.primary.used_percentserialized as a decimal with a.0suffix. This is consistent with the decoder mechanism described in #41566 (comment); I have not independently run that decimal/integer control on this binary.Controlled recovery evidence
Copies were tested with the same bundled app-server inside a network-isolated bubblewrap environment, with the real filesystem read-only. No model turn was started and no live conversation data was modified.
already_paginated.thread/turns/liststill returned 33/33 turns. The reconstructed database passedintegrity_check. A full event comparison found no changes to user/assistant message content; differences were ordinal renumbering and absent-to-null serialization normalization.This is recovery evidence from disposable copies, not a proposed general repair procedure.
Could maintainers confirm which desktop/bundled-runtime release includes the recovery handling in #42369, and whether upgrading automatically recovers already-stalled paginated checkpoints? A supported per-thread verification/recovery command would also help.
No raw transcripts, database files, project names, filesystem paths, credentials, or private session identifiers are attached.
gabriel-andreescu commentedon Sep 10, 2026
Two Windows recovery failures after unclean shutdowns on 0.153.4
Two local paginated chats show stale history while their JSONL transcripts continue receiving new records. One matches this issue's duplicate-ordinal pattern; the other has a zero-filled region and a stale byte checkpoint. They followed the same series of unclean shutdowns, but a shared code-level cause has not been established.
Environment
Case A: duplicate ordinal blocks projection and forking
Consecutive records at the failure boundary:
The projection checkpoint is exactly at the second ordinal 6253:
Every captured line parses as JSON, and this is the only ordinal discontinuity. The preceding token_count contains decimal serialization of used_percent as 0.0, consistent with the decoder discussion here; that mechanism has not been independently tested on this binary.
The desktop repeatedly fails thread/fork with code -32603:
The live writer reports the same mismatch while later messages continue being appended.
Case B: zero-filled region and a checkpoint inside a valid record
The invalid physical line is exactly b"\x00" * 159609 + b"\n". Excluding that line, valid records have a continuous ordinal sequence. This case has no duplicate ordinal.
The saved checkpoint is:
That byte offset is 97,300 bytes into the valid ordinal-14952 record. The actual current ordinal-14948 record starts at byte 113234671.
The materializer rejects the partial record at its stale checkpoint:
It then reports:
Two completed command outputs remain in SQLite at indexed ordinals 14944 and 14945, but their original item_completed events are absent from the current JSONL. Those outputs contain 57,094 and 22,513 characters. The current transcript now assigns those ordinals to post-restart records. A recovery that simply discards the projection could lose that retained content.
Shutdown correlation
The Windows System log confirms three unclean shutdowns on 2026-09-10. Times below are UTC.
Each boot also has Kernel-Power Event 41 with BugcheckCode=0. Case A's damaged transition spans the first outage episode and resume at 10:23:17. Case B's invalid region precedes resume at 11:11:13 after the later reboot. These establish correlation with unclean shutdowns, not the exact power-loss instant or a proven writer root cause.
Validation and recovery status
Expected behavior: prevent ordinal reuse after interruption, detect stale or invalid checkpoints, and provide recovery for already-affected paginated chats. Recovery should preserve any indexed content missing from the surviving transcript. A stalled projection should produce an actionable warning rather than silently showing old history as current.
PabloLION commentedon Sep 14, 2026
this works for ChatGPT Version 26.908.40834 too
Quesera008 commentedon Sep 15, 2026
Independent Windows reproduction of the same failure pattern.
Environment
OpenAI.Codex_26.908.9136.0_x640.150.101a08562-f5f4-7de1-8e38-418a342d5c4301a08b55-caf2-7a11-ad52-a342e9290f7bUser-visible symptom
After every desktop app restart, the thread returns to the same old conversation boundary from September 10. The visible last turn has no duration and appears interrupted, while later work from September 12–15 is missing from the UI. The project files produced by those later turns remain present.
Verified lifecycle state
Read-only SQLite inspection shows the stuck turn as:
The outer thread is currently reported as idle, while
read_threadexposes the old turn as interrupted. Newest-first history nevertheless stops at that old turn.Exact duplicate-ordinal boundary
The canonical rollout contains:
event_msg/token_countevent_msg/thread_settings_appliedevent_msg/task_startedThere is no
task_completebetween the earliertask_startedand this later task start.The history projection cursor stops at exactly this boundary:
Persisted tail
The original rollout remains valid and continues to:
The unprojected tail contains 10 later task starts, 10 matching task completions, 10 user messages, and 46 visible assistant messages. This independently confirms that later conversation data was durably written but hidden by the frozen projection.
A byte-identical SHA-256 backup was created before inspection. Neither the rollout nor either SQLite database was modified, and no lock was removed. Full conversation text, local paths, source code, credentials, and raw databases are intentionally omitted for privacy.
This looks like another direct reproduction of the unfinished-turn → duplicate
thread_settings_appliedordinal → permanently frozen history projection sequence described in the issue. A supported non-destructive reindex/repair path would be very helpful in addition to preventing new duplicate ordinals.