Repository navigation
ChatGPT macOS 26.901.51231: task history truncates at duplicate ordinal while later completed turns remain in JSONL #43640
Description
What version of the Codex App are you using (From “About Codex” dialog)?
ChatGPT macOS desktop app, version 26.901.51231, build 8109. The affected surface is a local coding task in the desktop app, not a terminal-only CLI session.
The installed, running application is named ChatGPT.app. These values were read from its Contents/Info.plist (the About dialog was not inspected):
CFBundleName / CFBundleDisplayName: ChatGPT
CFBundleExecutable: ChatGPT
CFBundleIdentifier: com.openai.codex
CFBundleShortVersionString: 26.901.51231
CFBundleVersion: 8109
Bundled runtime: codex-cli 0.153.4
The running desktop process has the bundled app-server as a child. Code-signing metadata identifies OpenAI OpCo, LLC. Reporting here because this repository provides the official desktop-app bug template; please route internally if the ChatGPT-branded desktop surface has a different owner.
What subscription do you have?
ChatGPT Pro, confirmed by the account owner.
What platform is your computer?
uname -mprs: Darwin 25.6.0 arm64 arm
macOS: 26.7 (25G227)
Hardware model: Mac14,9
Chip: Apple M2 Pro
Memory: 32 GiB
Timezone: Asia/Shanghai (UTC+08:00)
What issue are you seeing?
A visible task's loaded history appears to revert to early requirements from September 4, although the canonical JSONL contains later completed work through September 7 and ongoing activity on September 8. The history reader returns only three old turns, nextCursor: null, and hasMore: false. Its newest returned turn remains inProgress with no completion timestamp.
Read-only inspection identifies an exact duplicate-ordinal boundary: token_count(4341) is followed by thread_settings_applied(4341). The derived history cursor points to that second record but expects ordinal 4342. Retained runtime warnings explicitly report this mismatch. The projected turn/item tables and history-reader result agree with each other but are stale relative to the durable transcript.
This is missing content inside an existing task, not simply a task absent from the sidebar, and the affected task has history_mode = paginated, not legacy.
The account owner reported the UI discrepancy. The independent diagnostic evidence below comes from the desktop history tool, read-only SQLite queries, raw-record metadata, and local runtime logs; it is not an independently captured UI screenshot. Specific later completion records remain intact. This report does not claim that every historical record can be proven never to have been lost.
What steps can reproduce the bug?
Observed sequence on this affected installation
- Start a local desktop coding task on September 4 and continue it across multiple days, including tool execution and context compactions.
- The last September 4 record is
event_msg/token_count, ordinal4341. - On September 5, the same canonical rollout receives
event_msg/thread_settings_appliedwith ordinal4341again, followed bytask_startedat4342. The action that caused the writer to reuse the ordinal has not been established. A reboot, account switch, runtime change, or concurrent writer is not assumed. - Continue the task. Later work is completed on September 7, and those messages and completion events are persisted to the same JSONL.
- Inspect the task's historical conversation on September 8. The user reports old requirements as the latest loaded history. Repeated desktop
read_threadcalls return only the September 4 turns with no pagination cursor. - Compare the canonical rollout, the
threadsrow, thethread_history_1.sqliteprojection, and retained warnings: all identify the same stalled boundary described below.
This is a repeatable history-read failure on an already affected task, not yet a clean-install minimal reproduction of the writer defect. No raw transcript edits, projection repair, history reset, or application restart were performed during this investigation.
What is the expected behavior?
- Loading a task should include its durable later conversation and completed turns.
- A stale projection must not be presented as exhausted history (
hasMore: false) without an incomplete-history indication. - Resume/session transitions should not reuse persisted ordinals.
- A projection mismatch should be detected and safely reconciled, preserving canonical records; users need a supported rebuild/recovery path rather than manual database editing.
- One projection error should not leave an old turn indefinitely
inProgressor prevent unrelated task operations from working.
Additional information
All timestamps below are UTC. THREAD_A and TURN_1–TURN_3 are aliases, not real identifiers.
1. Canonical transcript versus derived projection
A complete-line prefix was captured for metadata analysis at 2026-09-08T01:27:31.256789+00:00. The task remains active, so later measurements can grow; these numbers refer to this fixed prefix only.
| Measurement | Observed value |
|---|---|
| Complete-line prefix size | 49,293,608 bytes |
| Physical JSONL records | 8,774 |
| JSON parse failures | 0 |
| Last prefix timestamp | 2026-09-08T01:27:30.091Z |
| Last prefix ordinal | 8772 |
| Ordinal discontinuities | Exactly 1: consecutive duplicate 4341 |
| Projection next byte offset | 19785902 |
| Projection expected next ordinal | 4342 |
| Complete records at/after the stalled cursor | 4,432 |
| Bytes at/after the stalled cursor | 29,507,706 |
Later task_complete events after the cursor |
15 |
| Materialized history turns | 3 |
| Materialized history items | 1,186 |
The state database's canonical path resolves to the inspected rollout. Its row has history_mode=paginated, archived=0, model_provider=openai, and stored session cli_version=0.153.0. The currently running bundled CLI reports 0.153.4; that difference alone is not proof of the trigger.
The fixed-prefix SHA-256 is 13bc5feb1ae73770b1ba420f0eda99ebcca9e9a54ce42711549e818ccd78c496. This is an identification checksum, not a public download of the transcript.
2. Exact boundary metadata (message/configuration payloads omitted)
| Physical line (1-based) | Byte offset (0-based) | Timestamp | Ordinal | Record type |
|---|---|---|---|---|
| 4342 | 19785002 | 2026-09-04T11:07:00.490Z | 4341 | event_msg/token_count |
| 4343 | 19785902 | 2026-09-05T02:05:51.182Z | 4341 | event_msg/thread_settings_applied |
| 4344 | 19787917 | 2026-09-05T02:05:51.187Z | 4342 | event_msg/task_started |
The stored cursor lands exactly on line 4343, the duplicate. The later ordinal sequence is contiguous in the captured prefix. This is not a malformed JSON line or an EOF-only artifact.
3. A later completion record exists but is beyond the loaded history
Physical JSONL line: 8569
Byte offset: 47269919
Ordinal: 8567
Timestamp: 2026-09-07T07:25:20.691Z
Record: response_item / message / assistant
Its message describes completed development, eight separately pushed commits, and a final regression result of 563 passed / 12 skipped (semantic summary, not a verbatim quotation). Local Git and acceptance artifacts independently corroborate that later work. Private repository details, message text, and commit identifiers are deliberately omitted.
4. Desktop history-reader result
Captured at approximately 2026-09-08T01:23:45Z, using the app-provided mcp__codex_app__read_thread tool:
{
"request": {
"threadId": "THREAD_A",
"hostId": "local",
"turnLimit": 6,
"includeOutputs": false,
"maxOutputCharsPerItem": 200
},
"page": {
"order": "newest_first",
"limit": 6,
"nextCursor": null,
"hasMore": false
},
"turns": [
{
"id": "TURN_3",
"status": "inProgress",
"startedAt": 1788511818,
"completedAt": null,
"itemCount": 500
},
{
"id": "TURN_2",
"status": "completed",
"startedAt": 1788509671,
"completedAt": 1788510806,
"itemCount": 0
},
{
"id": "TURN_1",
"status": "completed",
"startedAt": 1788504607,
"completedAt": 1788508225,
"itemCount": 0
}
]
}All three returned turns started on September 4. The itemCount values above are counts in the tool response, not database totals. In particular, the 500 count may be a wrapper limit; it is not claimed as the cause of the missing later turns.
At the matching timestamp, desktop AppServerConnection logs show thread/read, thread/turns/list, and thread/items/list responses routed with errorCode=null. I did not independently capture the raw lower-level RPC response bodies; hasMore=false above is the desktop tool's output.
The read-only projection query returns exactly these three turn states:
start ordinal 1: completed, end ordinal 375
start ordinal 380: completed, end ordinal 736
start ordinal 738: inProgress, end ordinal NULL
5. Runtime warnings and related operation failure
The retained logs_2.sqlite snapshot contains 384 matching WARN rows, across 1 process UUID, from 2026-09-07T07:12:42+00:00 through 2026-09-08T01:26:33+00:00. This is a retained-log observation, not the all-time count or proven first occurrence.
Target: codex_thread_store::local::live_writer. Exact message suffix with task IDs aliased:
failed to project durable rollout for THREAD_A: thread-store internal error: thread history projection for THREAD_A expected ordinal 4342, got 4341
Separate desktop logs contain five thread/revert failures for the same task between 2026-09-07T06:11:40.651Z and 2026-09-07T06:12:25.910Z, error code -32603:
failed to revert session: thread-store internal error: thread history projection for THREAD_A expected ordinal 4342, got 4341
Those failures occurred after the September 5 duplicate boundary; they do not establish what originally caused ordinal reuse.
6. Read-only validation method
- Open
~/.codex/state_5.sqlite,thread_history_1.sqlite, andlogs_2.sqlitewith SQLite URImode=roandPRAGMA query_only=ON. - Restrict queries to the affected task ID.
- Resolve the canonical rollout path from the
threadsrow; read a complete-line byte prefix, parse every JSONL record, and compare adjacent root-levelordinalfields without exporting message bodies. - Compare the projection byte cursor with the exact start of the duplicate record.
- Example projection queries (bind
:thread_id; do not modify any rows):
SELECT history_mode, cli_version, archived
FROM threads WHERE id = :thread_id;
-- Run the following against thread_history_1.sqlite:
SELECT next_rollout_byte_offset, next_rollout_ordinal
FROM thread_history_projection_state WHERE thread_id = :thread_id;
SELECT rollout_ordinal, status, started_at, completed_at,
rollout_end_ordinal
FROM thread_turns WHERE thread_id = :thread_id
ORDER BY rollout_ordinal;
SELECT item_type, COUNT(*)
FROM thread_items WHERE thread_id = :thread_id
GROUP BY item_type;7. Related reports and investigation request
Existing reports were searched before filing. This is additional evidence for the ChatGPT-branded macOS build 26.901.51231 / 8109:
- [macOS Desktop] Reboot can switch app-server runtime and wedge paginated history at a duplicate ordinal #40178 — closely matching duplicate-ordinal projection failure; this instance does not establish the reboot/runtime-switch trigger described there.
- Paginated history drops valid flattened rollout records and reuses ordinals #35746 — related ordinal reuse / paginated rollout handling.
- Resume opens a long thread at its first turn: 0.146.1 desynced thread_history projection cursors, and later versions never repair them #38792 — related projection-cursor reconciliation.
- Codex Desktop fails to render legacy-mode thread histories that are fully intact on disk (post-migration-0040) #34175 — similar visible-history symptom, but its legacy-mode scenario differs from this task's verified
paginatedmode.
Please link/triage with the existing defect if it is the same underlying issue. In particular, a regression test for token_count(N) → thread_settings_applied(N) → task_started(N+1) should check both durable-data preservation and subsequent history-reader pagination/status correctness.
Confirmed: duplicate ordinal, cursor exactly at that duplicate, matching projection warnings, stale derived tables, and omitted later durable completion records. Not established: the original writer-side trigger or whether rebuilding alone would remain healthy across future resumes. No repair was attempted.
No raw transcript, databases, credentials, internal URLs, business data, private paths, actual task IDs, or full logs are attached publicly. Sanitized metadata is inline above; private diagnostic identifiers can be provided through an appropriate support channel if needed.
Activity
github-actions commentedon Sep 8, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Gelan-D commentedon Sep 8, 2026
Additional independently inspected occurrence on ChatGPT macOS 26.901.51231 (build 8109), bundled codex-cli 0.153.4, macOS 26.6.2 arm64. The affected session's original metadata reports cli_version 0.153.0.
The same boundary appears twice in a single session:
token_count(1421)at2026-09-05T03:53:04.629Z→thread_settings_applied(1421)at2026-09-05T03:55:39.863Z→task_started(1422).token_count(5874)at2026-09-07T01:30:06.872Z→thread_settings_applied(5874)at2026-09-07T01:31:15.222Z→task_started(5875).The derived history projection is stuck at
next_rollout_ordinal=1422,next_rollout_byte_offset=37885157. The runtime repeatedly logs:The history-reading interface returns September 5 turns, including an old
inProgressturn, while the original JSONL still contains later completed work and user messages through September 8. The captured snapshot has no malformed JSON lines. An older separate conversation is fully projected and contains no duplicate ordinals.The model and reasoning settings were unchanged across both settings events. This does not establish the action that triggered ordinal reuse; no reliable clean-room reproduction is available.
Original session files and active databases have not been edited. We only performed read-only inspection, copied raw snapshots, and exported visible conversation text separately. The application history remains unrepaired.
Please ensure any recovery mechanism handles multiple collisions in one file, not just the first one. No private message bodies, real thread identifiers, project paths, credentials, or raw logs are included in this comment.
benfr97 commentedon Sep 8, 2026
Additional occurrence independently inspected on ChatGPT macOS 26.901.51231 (build 8109), macOS 27.0 arm64. Two local paginated tasks show missing recent history after quitting and reopening the app, while their canonical session JSONL files contain later activity. The user reports that new replies still appear to retain context from the hidden messages.
Read-only inspection on 2026-09-08 at approximately 11:35 UTC found:
In both cases, the next record is task_started with the expected ordinal (12,929 and 8,028 respectively). Both tasks have history_mode=paginated.
Retained desktop logs explicitly report:
The derived item tables for task A stop on September 2; task B's derived items stop on September 7. Both canonical session files continue through September 8.
A concrete user-recalled message in task B was located as an actual UserMessage event at 2026-09-08T10:44:32.937Z. A read-only query for its exact item ID in thread_items returned zero rows. Its text and identifier are intentionally omitted here. This is evidence of a specific saved user message missing from the derived history, beyond file-size or modification-time observations.
Task A's full JSONL scan during diagnosis parsed without malformed JSON lines. This does not establish sequence integrity or prove that every expected message survived. We have not performed a complete ordinal-anomaly inventory, determined the original writer-side trigger, or proven any repair.
No original session files, active databases, settings, or task state have been changed. No raw logs, screenshots, conversation bodies, private paths, task titles/IDs, credentials or database files are attached.
Please include this in the existing investigation and provide a supported, preservation-first repair path for existing affected tasks, alongside prevention of recurrence. A successful recovery should demonstrate that later user/assistant items are readable and remain available after another app restart.
ArnaudLafosse92100 commentedon Sep 8, 2026
Resume reuses a trailing token_count ordinal and stalls history projection
Additional controlled reproduction for this issue. No conversation content,
account identifiers, authentication material, or personal paths are included
in the report body. No raw transcripts or databases are attached.
Environment
Controlled reproduction
Run the bundled official
codex app-server --stdiowith an isolated CODEX_HOMEand copies of its state/history databases and one transcript prefix. Point the
isolated state row to the copied transcript. Do not use active originals.
Treatment transcript ends in a valid
event_msg/token_count, ordinal 5089.Its history cursor is at EOF, expecting ordinal 5090.
JSON-RPC sequence: initialize with experimentalApi enabled; thread/resume with
excludeTurns true; thread/settings/update with effort low; close stdin and wait
for graceful app-server exit.
Observed appended event:
thread_settings_applied, ordinal 5089. Expected:5090. The history cursor does not advance. This recreates the production symptom.
Control: same transcript prefix, but without only that last token_count record.
EOF now expects 5089. The identical request sequence appends settings at 5089
and the history cursor advances to 5090. Control passes.
Both cases were reproduced twice with the same installed official binary.
An additional real history contained TWO final token_count events before resume
and reused the first of their ordinals, consistent with the same mechanism.
Impact
The writer continues to persist conversation content, but the strict history
projector stops at the reused ordinal. Desktop history therefore appears stale
or missing after reopening conversations. Rebuilding only the derived index
restores visibility but cannot prevent another recurrence.
Proposed fix contract (source implementation not verified)
The resumed writer must derive its next durable ordinal from the actual durable
file sequence, including metadata not retained in reconstructed model history.
Filtering token_count from model context must not rewind the durable append
counter. Also account for multiple writers/appends when finalizing allocation.
The recovery/migration path should preserve message content and safely handle
already-produced duplicate/backtracking metadata ordinals rather than silently
stalling all subsequent history. Avoid blindly relaxing sequence checks for
arbitrary malformed records.
Required regression coverage
Local recovery evidence
On the isolated failing treatment, changing ONLY its derived projection cursor
from expected 5090 to 5089 lets the native engine consume the duplicate settings
record and its next append; the cursor advances to 5091. This is narrow recovery,
not a permanent prevention mechanism. Originals were not modified by the test.
V-DeVito commentedon Sep 11, 2026
Additional occurrence confirmed in a long-running local paginated conversation on ChatGPT macOS 26.903.61454 (build 8378), bundled codex-cli 0.153.4, macOS 26.3. Inspected September 10 local / September 11 UTC.
The user reports that recent conversation progress repeatedly disappears from the visible history and returns to the same older point.
Read-only inspection found this exact boundary:
The derived history cursor is byte 685516830, expecting ordinal 137912, but the record at that exact byte is the duplicate 137911. Unlike some examples above, the duplicate at this boundary is task_started, not thread_settings_applied.
Retained WARN logs for this same task explicitly report:
This warning was still present at 2026-09-11T02:48:52Z.
At an earlier fixed inspection point, the canonical transcript was 804279396 bytes and contained later records through 2026-09-11T02:48:06.231Z, ordinal 153997. Thus roughly 119 MB of later durable records exist beyond the stalled cursor. This is evidence of persisted later records, not proof that every expected message survived.
The original writer-side trigger has not been established locally. No app restart, live transcript renumbering, database repair, revert, or cache reset was performed during this diagnosis. We are preserving private snapshots and extracting readable messages separately, not modifying the active source.
Please provide a supported repair for already-affected histories as well as prevention of further ordinal reuse. A recovery should preserve user/assistant/tool content and demonstrate that later turns remain visible after restart. No private transcript content, real task IDs, project paths, database files, or credentials are included in this report.