Thread store resolves stale session_index entries to missing rollout files (state db returned stale rollout path)
Summary
The local session index (~/.codex/session_index.jsonl) retains entries whose rollout
JSONL no longer exists in either the live sessions tree or archived_sessions/. When the
app/thread store resolves such a thread id, it returns a path to a missing file and errors
instead of falling back to the archived copy or self-healing the index. On a
long-lived, high-session-volume host this accumulates: 113 of 283 indexed entries (40%)
had no backing rollout file anywhere.
Evidence
Codex's own log reports the inconsistency from inside codex_rollout::list:
ERROR codex_rollout::list: state db returned stale rollout path for thread
019f2339-9299-7e51-b192-9751a0a03586:
/home/USER/.codex/sessions/2026/07/02/rollout-2026-07-02T14-26-43-019f2339-...jsonl
That file is not in live sessions/, not in archived_sessions/ (507 archived JSONLs
present), and not found by a recursive basename search.
Audit of the index on the affected host:
index entries: 283 | present (live or archived): 170 | STALE (no backing file): 113
A second, related failure mode also seen: a rollout file that exists but is misfiled —
stored under sessions/2026/05/09/ while its contents begin with 2026-07-03 data and do
not start with a session_meta record. So the index/path bookkeeping and the on-disk
partitioning can disagree in both directions (missing file; misplaced/malformed file).
How it likely arises
The index write and the rollout file lifecycle (create / archive-move / delete) are not
crash-consistent. If the process is interrupted between updating the index and finalizing
the file — e.g. an ENOSPC disk-full (our trigger: root fs hit 100%), a SIGKILL, or an
archival move that half-completes — the index keeps an entry the filesystem can't satisfy.
Nothing later reconciles it.
Impact
- App/thread resolution errors when opening or listing affected threads.
- Users cannot cleanly resume or reference historical sessions that are actually still
recoverable from durable artifacts.
- Grows unbounded on active hosts; 40% stale observed.
Expected behavior (any of)
- On resolve-miss, fall back to
archived_sessions/(and a basename search) before erroring. - Self-heal the index: drop or flag entries whose rollout file is absent from both live
and archived locations, rather than repeatedly resolving to a dead path.
- Make the index update + rollout finalize crash-consistent (write file first / fsync +
atomic rename, update index only after), so an interrupted write can't orphan an entry.
- Provide a
codexsubcommand to verify/repair the session index.
Workaround in use
Local reconciliation script: back up session_index.jsonl, drop entries with no backing
rollout file in live or archived sessions (never deletes rollout files). Mitigates the
resolve error until a first-class fix lands.
Related issues (adjacent but distinct)
Several open issues touch "stale rollout path," but each is tied to a specific Desktop UI
flow rather than the crash/interruption-consistency root cause and the systemic 40%
accumulation reported here (observed via codex-cli / app-server, not a UI action):
- #26201 / #26174 — stale archived rollout path after archive/unarchive
- #30924 — "failed to resolve rollout path" on new conversations (Windows Desktop)
- #23991 — delete leaves session-index residue
- #21663 — missing rollout path → macOS SIGABRT
This report is about the index and rollout-file lifecycle becoming inconsistent when a
write is interrupted (ENOSPC / SIGKILL / half-completed archival move), independent of
any UI flow, and the index then never self-reconciling. Please link/dedupe as appropriate.
Environment
- codex-cli 0.142.5, Linux (Ubuntu 22.04), standalone install
~/.codexon local disk; hundreds of live + 507 archived sessions- Trigger correlated with a root-filesystem ENOSPC event (0 bytes free) during an archival burst
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗