thread/list filesystem fallback can hide older matching threads after hitting 10,000-file scan cap
What version of Codex CLI is running?
codex-cli 0.116.0
What subscription do you have?
Plus
Which model were you using?
N/A — this appears to be a local thread listing / resume-history bug, not model-specific
What platform is your computer?
Darwin 25.4.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
Codex desktop app terminal
What issue are you seeing?
thread/list can falsely report that there are no more matching threads when the server is using filesystem fallback and the rollout scan hits the hard 10,000-file cap before reaching older matching sessions.
Impact:
- history UIs can appear incomplete
- filtered
thread/listcalls can returndata = []withnextCursor = nulleven though older matching threads still exist - fallback latest-session lookup can stop early and behave as if no matching session exists
This appears to affect the rollout-scanning path rather than the SQLite-backed path.
From reading the local source:
- hard cap is
MAX_SCAN_FILES = 10000incodex-rs/rollout/src/list.rs - the traversal code only marks
more_matches_available = trueafter hitting the cap if at least one matching item was already found - so if the newest 10,000 rollout files are all filtered out by provider/source/cwd, the page can terminate as if exhausted even though older matching threads still exist
Relevant code:
codex-rs/rollout/src/list.rsaround the scan cap handling in:traverse_directories_for_paths_createdtraverse_directories_for_paths_updatedtraverse_flat_paths_createdtraverse_flat_paths_updated
In each case the logic is effectively:
let reached_scan_cap = scanned_files >= MAX_SCAN_FILES;
if reached_scan_cap && !items.is_empty() {
more_matches_available = true;
}
That !items.is_empty() condition appears incorrect for filtered queries.
What steps can reproduce the bug?
I have not yet reproduced this from a normal end-user session; this report is based on source analysis of the local checkout.
A synthetic repro should look like this:
- Create more than 10,000 rollout files under
~/.codex/sessions/.... - Ensure the newest 10,000 files do not match a chosen filter, for example:
- different
model_provider, or - different
source, or - different
cwd
- Ensure there are older rollout files beyond that scan window that do match the filter.
- Call
thread/listwith that filter. - Observe that the filesystem fallback path can return:
data = []nextCursor = null
even though older matching threads still exist.
High-level repro shape:
- newest 10,000 rollouts: provider =
skip_provider - older rollouts after that: provider =
target_provider - query:
thread/listwithmodelProviders = ["target_provider"]
Expected:
- pagination should continue, or the response should otherwise indicate that older matches may still exist
Actual:
- the filesystem path can terminate as if exhausted once the scan cap is hit before any matching item is found
I found the relevant control flow here:
codex-rs/rollout/src/list.rscodex-rs/rollout/src/recorder.rsfallback listing path
What is the expected behavior?
When filesystem scanning hits the 10,000-file cap before finding a matching thread, thread/list should not claim the result set is exhausted.
Expected behavior:
- if the scan cap is hit before the server can prove exhaustion, the response should preserve a continuation path rather than returning
nextCursor = null - older matching threads should remain discoverable even when many newer non-matching rollouts exist
- fallback latest-session/history lookup should not stop early and behave as if there is no matching session
Additional information
Additional code references:
- hard cap:
codex-rs/rollout/src/list.rs- filesystem fallback entrypoint:
codex-rs/rollout/src/recorder.rs- SQLite-backed list path does not appear to have this exact failure mode:
codex-rs/rollout/src/state_db.rs
I also checked existing open issues/PRs and did not find a direct report for this specific scan-cap behavior.
This looks especially relevant for users with:
- large local thread history
- provider/source/cwd filters
- fallback listing paths when SQLite is unavailable, incomplete, or bypassed
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗