All historical conversations missing from sidebar after auto-update; local data is intact

Resolved 💬 3 comments Opened May 8, 2026 by xiaohuli-zy Closed May 9, 2026

What version of the Codex App are you using (From “About Codex” dialog)?

26.506.21252 (build 2575)

What subscription do you have?

ChatGPT login (Pro Lite plan), single Personal organization

What platform is your computer?

macOS (Darwin 25.2.0)

What issue are you seeing?

What's still on disk (verified):

  • ~/.codex/state_5.sqlite — threads table contains all 90 thread records
  • ~/.codex/sessions/**/.jsonl and ~/.codex/archived_sessions/.jsonl — all 90 corresponding rollout files exist; every rollout_path in threads resolves to a real file (90/90 match)

Root cause I was able to narrow down:
The schema migration v30: threads thread source (installed 2026-05-08 05:01:28) added the thread_source column, and migrations earlier added created_at_ms / updated_at_ms. For all pre-existing threads, these
three columns were left at their default empty/NULL values — only newly created 0.129.0 threads have them populated. The backfill_state row is set to status = 'complete' with last_success_at = 1774857949 (a
timestamp earlier than any thread in the table), so the backfill appears to have been marked complete without actually running against existing data.

What I tried:

  1. Re-login (ChatGPT account, same email as before) — no change.
  2. Manually backfilled the missing fields with the obvious derivations:
  • UPDATE threads SET created_at_ms = created_at * 1000 WHERE created_at_ms IS NULL;
  • UPDATE threads SET updated_at_ms = updated_at * 1000 WHERE updated_at_ms IS NULL;
  • UPDATE threads SET thread_source = 'user' WHERE thread_source = '' OR thread_source IS NULL;
  1. WAL-checkpointed and fully restarted the app.

After step 2 + 3, every project still shows "No conversations" and the archived list is still empty. So there is at least one additional filter beyond thread_source / created_at_ms / updated_at_ms that excludes
the migrated rows.

Suspicious strings found inside the codex binary:
state db discrepancy during list_threads_with_db_fallback: falling_back
state db discrepancy during list_threads_db: stale_db_path_dropped
state db discrepancy during find_thread_path_by_id_str_in_subdir: stale_db_path / mismatched_db_path / falling_back
state db discrepancy during read_repair_rollout_path: upsert_needed (fast/slow path)
A list_threads_with_db_fallback code path clearly exists, but it does not appear to be triggered for these legacy rows even though their data and rollout files are valid. The renderer-side call is:
client.listThreads({
limit: 100,
cursor: null,
sortKey: 'updated_at',
modelProviders: null,
sourceKinds: <enum>,
archived: false,
})
Whatever set of sourceKinds the UI passes by default seems to be excluding all migrated rows.

Expected behavior:
After upgrading, the existing conversations should remain visible in the sidebar (under their respective project folders) and in the archived list, without any manual SQLite intervention by the user.

Severity: High — this looks like silent data loss to a normal user, even though the data is actually intact. Users without database tooling will have no way to recover their history.

What steps can reproduce the bug?

What's still on disk (verified):

  • ~/.codex/state_5.sqlite — threads table contains all 90 thread records
  • ~/.codex/sessions/**/.jsonl and ~/.codex/archived_sessions/.jsonl — all 90 corresponding rollout files exist; every rollout_path in threads resolves to a real file (90/90 match)

Root cause I was able to narrow down:
The schema migration v30: threads thread source (installed 2026-05-08 05:01:28) added the thread_source column, and migrations earlier added created_at_ms / updated_at_ms. For all pre-existing threads, these
three columns were left at their default empty/NULL values — only newly created 0.129.0 threads have them populated. The backfill_state row is set to status = 'complete' with last_success_at = 1774857949 (a
timestamp earlier than any thread in the table), so the backfill appears to have been marked complete without actually running against existing data.

What I tried:

  1. Re-login (ChatGPT account, same email as before) — no change.
  2. Manually backfilled the missing fields with the obvious derivations:
  • UPDATE threads SET created_at_ms = created_at * 1000 WHERE created_at_ms IS NULL;
  • UPDATE threads SET updated_at_ms = updated_at * 1000 WHERE updated_at_ms IS NULL;
  • UPDATE threads SET thread_source = 'user' WHERE thread_source = '' OR thread_source IS NULL;
  1. WAL-checkpointed and fully restarted the app.

After step 2 + 3, every project still shows "No conversations" and the archived list is still empty. So there is at least one additional filter beyond thread_source / created_at_ms / updated_at_ms that excludes
the migrated rows.

Suspicious strings found inside the codex binary:
state db discrepancy during list_threads_with_db_fallback: falling_back
state db discrepancy during list_threads_db: stale_db_path_dropped
state db discrepancy during find_thread_path_by_id_str_in_subdir: stale_db_path / mismatched_db_path / falling_back
state db discrepancy during read_repair_rollout_path: upsert_needed (fast/slow path)
A list_threads_with_db_fallback code path clearly exists, but it does not appear to be triggered for these legacy rows even though their data and rollout files are valid. The renderer-side call is:
client.listThreads({
limit: 100,
cursor: null,
sortKey: 'updated_at',
modelProviders: null,
sourceKinds: <enum>,
archived: false,
})
Whatever set of sourceKinds the UI passes by default seems to be excluding all migrated rows.

Expected behavior:
After upgrading, the existing conversations should remain visible in the sidebar (under their respective project folders) and in the archived list, without any manual SQLite intervention by the user.

Severity: High — this looks like silent data loss to a normal user, even though the data is actually intact. Users without database tooling will have no way to recover their history.

What is the expected behavior?

_No response_

Additional information

_No response_

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗