Repository navigation
Backtrack rewind sets context remaining to 0% and triggers auto-compaction #9601
Copy link
Copy link
Open
Labels
TUIIssues related to the terminal user interface: text input, menus and dialogs, and terminal displayIssues related to the terminal user interface: text input, menus and dialogs, and terminal displaybugSomething isn't workingSomething isn't workingcontextIssues related to context management (including compaction)Issues related to context management (including compaction)
Description
Summary
After using the TUI backtrack/rewind flow (Esc to open transcript overlay, select a previous user message, Enter to rollback), the context indicator jumps to 0% left and the next turn is auto-compacted, even when the post-rollback thread should be far below the model context window.
Version
- Repo:
openai/codex - Commit:
16b9380e99474c87502c22ed99bac497d116e724
Repro
- Start a Codex TUI session and exchange a few turns (enough to have non-empty history).
- Confirm the bottom-bar context indicator is not near
0% left. - Press
Esctwice to open the transcript overlay (backtrack preview). - Use
Leftto select an earlier user message. - Press
Enterto rollback. - Observe the context indicator becomes
0% leftand the next user turn triggers an automatic compact.
Expected
- After rollback, token/context usage reflects the smaller history and the context indicator shows substantial remaining context.
- Auto-compact should not run unless the post-rollback prompt actually exceeds the auto-compact threshold.
Actual
- Immediately after rollback, remaining context shows
0% left. - A compact runs even when the post-rollback thread should be well below the context window.
Suspected cause
The rollback handler recomputes token usage from a heuristic estimate rather than server-provided token usage:
codex-rs/core/src/codex.rs:2522handlers::thread_rollback(...)callssess.recompute_token_usage(...).codex-rs/core/src/codex.rs:1626Session::recompute_token_usage(...)usesContextManager::estimate_token_count(...).codex-rs/core/src/context_manager/history.rs:87estimate_token_count(...)estimates by JSON-serializing history items (serde_json::to_string(item)) and then calling byte/token heuristics.
This can drastically overestimate the prompt size (JSON framing overhead, large structured fields, image/base64 fields, etc.), which then drives:
- The TUI context indicator (
codex-rs/tui/src/chatwidget.rs:906usesinfo.last_token_usage.percent_of_context_window_remaining(window)) - The auto-compact guard (token usage estimate feeds
get_total_token_usage/auto_compact_token_limit).
Possible fixes
- After rollback, clear token usage info (emit
TokenCount { info: None }) until the next real model response provides accurate counts. - Or, compute the estimate from the normalized prompt representation (same normalization used for
for_prompt()), and avoid counting JSON framing. If images are present, estimate image token cost instead of base64 length.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
TUIIssues related to the terminal user interface: text input, menus and dialogs, and terminal displayIssues related to the terminal user interface: text input, menus and dialogs, and terminal displaybugSomething isn't workingSomething isn't workingcontextIssues related to context management (including compaction)Issues related to context management (including compaction)
Activity
0xdeafbeef commentedon Jan 21, 2026
Same thing if you change model and compact.
sahir2k commentedon Jan 22, 2026
facing this as well
swordfish444 commentedon Jan 26, 2026
@etraut-openai This looks like the same symptom family as #9417 / #9257 (“context remaining goes to 0% after a history mutation”), just triggered by backtrack/rollback instead of compaction.
The suspected cause in the report seems plausible:
recompute_token_usageestimating fromserde_json::to_string(item)will overcount (JSON framing + large structured fields), which can push the indicator to 0% and trip auto-compact.A low-risk stopgap could be: after rollback, clear token usage info (treat as unknown) until the next real server-provided token count arrives. That avoids bogus “0% remaining” and unnecessary auto-compaction.
Longer term, it seems safer to estimate from the normalized prompt representation (what’s actually sent) rather than serialized history structs.
Alek2077 commentedon Feb 19, 2026
Facing the same issue. It permanently burns my sessions, some of which are very important.
So now it's clear the huge disadvantages Codex CLI has over some of the other tools:
These are huge usability features.
miraclebakelaser commentedon Feb 20, 2026
This has become a constant issue for me when backtracking. Context frequently gets crushed to 0%.
Pasting an image into a conversation perpetually poisons, even after compactions. Every single backtrack following an image input will lead to 0% context.
Alek2077 commentedon Feb 20, 2026
@miraclebakelaser I managed to change from 0% to 90%+ by messing with
model_auto_compact_token_limitin toml.configand starting the convo with the flag
codex resume --last --autocompact=offand
codex resume --last -c model_auto_compact_token_limit=10000000,but unsure how usable the conversation is anymore. I just started a new convo..
miraclebakelaser commentedon Feb 20, 2026
@Alek2077
codex resume --last --autocompact=offdoesnt seem like a valid command.codex resume --last -c model_auto_compact_token_limit=10000000doesn't fix the issue for me. The conversation resumes at 0% context.Alek2077 commentedon Feb 20, 2026
@miraclebakelaser My bad, the first one indeed is invalid command, but something did fix it - either increasing the model_auto_compact_token_limit in config.toml, or running directly on the 'resume' command. Try it, try increasing compaction to 300k, that's above the max limit, it might actually prevent compacting completely. Let it run for one turn, see if compaction happens and if not, after Codex does one turn, it might change the percentage.
but again, these are just workarounds and we do need a proper fix.
runfence commentedon Jun 5, 2026
Same issue. I was around at 80%, asked a few questions, then reverted to 80% point and asked another question which triggered compaction.
moulwyse commentedon Sep 9, 2026
The suspected cause in the report points at a failure mode worth naming
explicitly: the session carries two different token accountings, and only
one of them is authoritative.
estimate_token_countis a local heuristic.usage(input_tokens,output_tokens,input_tokens_details.cached_tokens) is what the backend actuallycounted and truncated against.
Rollback recomputes from the heuristic, so the displayed remaining context
is not a measurement — it is a re-derivation. That is consistent with
landing on
0% leftfor a history the server would have accepted.There is a second derivation on the other side of the same ratio. Recent
CLI versions emit token-usage events with
model_context_window: 258400while the bundled catalog carries
context_window: 272000— exactly 95%.So the indicator is an estimated numerator over a discounted denominator.
Two independent approximations compound, which matches reports of
compaction firing well below the real limit.
Suggested behaviour, in order of preference:
provider-reported usage associated with the retained prefix.
unknown rather than
0%, and defer the auto-compaction decisionuntil the next model response returns real
usage.operation. Compaction is destructive; it should require a reported
number, not an inferred one.
If useful, I can contribute a measurement rather than an opinion: the same
session replayed with rollback, logging
estimate_token_countagainstprovider-reported
input_tokensat each turn, to quantify the drift inabsolute tokens instead of percent. I maintain an Apache-2.0 tool that
already records provider-reported usage per call for this kind of
comparison, so the instrumentation exists. Happy to run it and paste the
table here if that would help triage.