TUI /resume can show No sessions yet when cwd-filtered thread/list drops state DB matches
Summary
The TUI /resume picker can display No sessions yet for the current working directory even when matching sessions exist in the local Codex state DB and can still be resumed directly by ID.
In the local repro, the same session was:
- visible in local history/state metadata,
- resumable with
codex resume <session-id>, - returned by
thread/listwhenuseStateDbOnly: truewas used, - but omitted by the default scan-and-repair
thread/listpath used by the TUI/resumepicker with a cwd filter.
This appears related to #22037 and the lower-level issue described in #22777, but the visible CLI/TUI failure mode here is a correctness issue: the picker says there are no sessions, not only that listing is slow.
Environment
- Codex CLI: observed on
0.139.0 - Surface: CLI/TUI
/resume - Platform: Linux container
- Local state layout:
CODEX_HOMEis a symlink to persistent storage
The symlinked CODEX_HOME layout does not appear to be the root cause. The relevant session files and SQLite state DB were readable, and direct resume by session ID worked. I am mentioning it only because it was part of the observed environment.
Reproduction shape
- Have existing sessions in
$CODEX_HOME/sessionswhose metadata in the state DB matches a project cwd. - Start
codexfrom that project directory. - Run
/resume. - Observe the picker shows
No sessions yetfor the cwd-filtered view. - Run
codex resume <session-id>for one of those sessions. - The session resumes successfully.
- Compare
thread/listbehavior for the same cwd filter:
- default scan-and-repair listing returns no rows for that cwd,
useStateDbOnly: truereturns the expected rows.
No raw rollout JSONL, full local paths, auth/config files, or session contents are needed to reproduce the code-path issue.
Root cause hypothesis
RolloutRecorder::list_threads_with_db_fallback currently treats source/provider/cwd/search filters as metadata-filtered listings. When the state DB is available, it queries SQLite and can see matching rows, but for metadata-filtered listings it returns the filesystem scan page rather than the DB page.
That makes valid state DB matches disappear whenever the filesystem summary scan does not produce a ThreadItem for them. One concrete way this can happen is when a rollout has valid session_meta but the first preview-bearing user event is outside the limited head scan window. In the TUI /resume cwd-filtered path, that can surface as No sessions yet even though the state DB has the session and direct resume works.
Expected behavior
For source/provider/cwd-filtered listings, if the state DB is available and contains matching valid rows, the returned first page should include those rows after reconciliation. The filesystem scan should remain a fallback/repair path, not the authoritative returned page when SQLite has already produced a valid filtered result.
Patch experiment
I tested a small patch in a fork that changes non-search metadata-filtered listings to:
- run the existing filesystem scan and repair for filesystem hits,
- query the state DB,
- fully reconcile DB-only hits so stale cwd/provider/source metadata is still corrected,
- re-query and return the repaired DB page when SQLite is available,
- keep the existing filesystem fallback when SQLite is unavailable or errors.
Patch commit:
https://github.com/Moujuruo/codex/commit/93130eeb3f9bc93999fdfd20f2dbc82568d2d1fd
I kept searchTerm behavior separate because search has its own fallback semantics when the DB has not been warmed yet.
Validation run on the patch
just fmtjust test -p codex-rollout list_threads_cwd_filter_returns_state_db_only_match list_threads_default_filter_reconciles_stale_state_db_hits list_threads_search_repairs_stale_state_db_hits_before_returningjust test -p codex-rollout(70 passed)just fix -p codex-rollout
Why this is not just a symlink problem
The local CODEX_HOME symlink was durable and readable. The same sessions could be found by ID and by state-DB-only listing. The failing path was specifically the default scan-and-repair listing used by /resume with cwd/source/provider filters returning the filesystem scan page after state DB lookup.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗