[BUG] /context shows 76% header but Messages category shows 138.7% — "Context limit reached" on resume of session within stated free space

Status Fixed / completed
Reported on v2.1.114
Maintainer reply None cached
Activity 4 comments · opened Apr 19, 2026 · closed May 6, 2026

Summary

After resuming a session that was closed the previous evening at ~74% context (26% free), the next message attempt is rejected with Context limit reached · /compact or /clear to continue. The /context command output is internally inconsistent: the header reports 764.2k/1m tokens (76%) while the per-category breakdown lists Messages: 1.4m tokens (138.7%). The numbers cannot both be true. The displayed header gives no indication that the session is actually over the limit, so the rejection feels like a regression of the resume token-accounting behavior.

This appears to be a remaining variant of the bug reportedly fixed in v2.1.98 ("Fixed /context Free space and Messages breakdown disagreeing with the header percentage") and is also closely related to #46047 ("Resumed conversations incorrectly recount context tokens as new usage", closed as duplicate).

Reproduction

  1. Use Claude Code with model claude-opus-4-7 (1M context variant) for a long session involving many large tool_result payloads (in my case: MCP tool calls returning ~100–800 KB JSON each, plus several large Read results and Chrome DevTools screenshots).
  2. Trigger one or more in-session compactions until the session contains ≥ 4 compaction summary markers.
  3. Close Claude Code at a context level that the header reports as ~74% used / 26% free.
  4. The next day, \claude --resume <session-id>\ to continue.
  5. Run \/context\ and observe the inconsistent header vs. per-category numbers.
  6. Try to send any message.

Expected behavior

Either:

  • (a) The header \% used\ reflects the actual tokens that will be sent to the API, and a session at 76% should accept at least one further message, or
  • (b) If the session truly is over the model context limit, the header should also display ≥ 100%, not 76%.

The two displays must agree, and the displayed value must match what the API server enforces.

Actual behavior

\/context\ output (verbatim):

\\\`
Context Usage
764.2k/1m tokens (76%)
claude-opus-4-7[1m]

Estimated usage by category
⛁ System prompt: 9.7k tokens (1.0%)
⛁ System tools: 17.4k tokens (1.7%)
⛁ MCP tools: 18.7k tokens (1.9%)
⛁ Custom agents: 675 tokens (0.1%)
⛁ Memory files: 10.6k tokens (1.1%)
⛁ Skills: 2.4k tokens (0.2%)
⛁ Messages: 1.4m tokens (138.7%)
⛁ Compact buffer: 3k tokens (0.3%)
\\\`

Sum of the categories ≈ 1.46M, header reports 0.764M. Sending any message returns:

\\\
Context limit reached · /compact or /clear to continue
\
\\

Environment

  • Claude Code: 2.1.114
  • Node: v22.20.0
  • OS: Ubuntu 24.04.3 LTS on WSL2 (Linux 6.6.87.2-microsoft-standard-WSL2 x86_64)
  • Plan: Max
  • Model: \claude-opus-4-7[1m]\ (1M context)

Session evidence

I was able to inspect the session JSONL on disk (\~/.claude/projects/<project>/<session>.jsonl\):

  • File size: 21.5 MB
  • Lines: 5819
  • Tool-uses recorded: 1787
  • Compaction summary markers in stream: 4
  • Pre-compact region (before the latest compaction summary): 6 MB
  • Post-compact region (latest compaction summary + everything after): 14.5 MB
  • Largest 15 \tool_result\ payloads in the post-compact region: 1.96 MB combined (largest single result: a 195 KB Chrome DevTools screenshot, present twice in the file with the same \tool_use_id\ — once at line 127 in pre-compact, once at line 2736 in post-compact, byte-identical)

The presence of identical pre/post-compact \tool_result\ duplicates with the same \tool_use_id\ strongly suggests resume-time recounting (cf. #46047): the same payload is being held in memory and counted both as part of the pre-compaction history and as a fresh post-resume tool_result.

Pre-compact references from post-compact messages confirm the linkage:

  • 1617 of 3167 post-compact \parentUuid\ values point at pre-compact \uuid\s
  • 588 of 1118 post-compact \tool_result.tool_use_id\ values point at pre-compact \tool_use\ IDs

So the post-compact region cannot be safely trimmed by simply deleting the pre-compact region (UUID/tool-use chain would break), but the CLI also seems to be sending — or accounting for — both regions in full, even though the latest compaction summary is supposed to replace pre-compact content for the API stream.

Workaround attempted

I duplicated the session file, then surgically replaced the \content\ of the 15 largest post-compact \tool_result\ items with a stub string while preserving every \uuid\, \parentUuid\, \tool_use_id\, \type\, and \name\ field. JSONL line count, UUID set hash, parentUuid set hash, and tool_use_id set hash are all byte-identical to the pre-trim file. New file size: 18.64 MB (-1.87 MB).

Result on resume: \/context\ still shows the same \Messages: 1.4m tokens (138.7%)\ discrepancy, and writing is still blocked. This further suggests the counter / API-stream construction is not just naively summing on-disk content — there is some other state (possibly the same recount bug as #46047) that the trim does not affect.

Impact

  • Long sessions on the 1M model become unrecoverable: \/compact\ and \/clear\ both destroy work that was specifically being preserved by not triggering compaction.
  • The header \%\ is actively misleading — it suggests the user has plenty of room when they have none.
  • Trust in \/context\ as a planning tool is broken: I closed the session at a reading I now know was wrong, and could not have predicted the next-day failure.

Suggested investigation

  1. Audit the \/context\ aggregator: under what conditions can the per-category sum exceed the header total? Make this an internal invariant violation that surfaces a warning rather than two contradictory numbers.
  2. Check whether resumed sessions reload pre-compaction \tool_result\ payloads into the API stream when a compaction summary should already cover them (link to #46047).
  3. Make the enforced token figure (the one the API server will reject against) the canonical value displayed in the header.

Related

  • #46047 — Resumed conversations incorrectly recount context tokens as new usage (closed as duplicate)
  • #34158 — Context limit reached at ~200K tokens despite 1M context model
  • #11335 — Context Remaining Display Shows 0% When ~50% Available
  • Changelog 2.1.98 — Fixed /context Free space and Messages breakdown disagreeing with the header percentage (this report shows the fix is incomplete on 2.1.114)

View original on GitHub ↗

4 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/41181
  2. https://github.com/anthropics/claude-code/issues/47855
  3. https://github.com/anthropics/claude-code/issues/18241

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

blackdiamond6390 · 5 months ago

Update: Downgrade hypothesis tested and falsified

To narrow down whether this is a recent regression, I downgraded the duplicated session file (kept original untouched) and re-tested resume + write at four progressively older versions:

| Version | Result | Notes |
|---|---|---|
| 2.1.114 | ❌ blocked | original repro (current latest at time of report) |
| 2.1.111 | ❌ blocked | |
| 2.1.110 | ❌ blocked | |
| 2.1.105 | ❌ blocked | |
| 2.1.97 | ❌ blocked | explicitly PRE the 2.1.98 fix ("Fixed /context Free space and Messages breakdown disagreeing with the header percentage") |

The bug reproduces identically across all five versions. This rules out a regression introduced in 2.1.98–2.1.114 and rules out the hypothesis that the 2.1.98 fix itself caused this edge case.

The block also persisted after I surgically stubbed the 15 largest post-compact tool_result payloads (1.87 MB / ~470k tokens removed, UUID/parentUuid/tool_use_id sets byte-identical to pre-trim — verified by hash). /context still reports the same Messages: 1.4M (138.7%) discrepancy on the trimmed file, which suggests the displayed Messages count is not a function of the on-disk JSONL bytes alone — there is some additional in-memory or cache state that /context aggregates and that file edits do not reset.

This makes #46047 (resume-time recounting) feel like the more likely root cause than a /context aggregator bug per se.

Reinstall path used for each test:

npm install -g @anthropic-ai/claude-code@<version>
bhosmer-ant · 5 months ago

Hi @blackdiamond6390 - should be fixed in 2.1.129, but if you're still seeing the problem on that version or later, please open a new issue referencing this one.

Claude summary of the problem details and fix:
---
What was happening: when a long conversation auto-compacted in fullscreen mode, the compaction marker wasn't being saved to the session file on disk. The compaction worked in-memory — context dropped, the session continued — but on the next resume, the loader couldn't see it and reloaded everything since the last saved marker. That's why /context showed Messages well over 100% right after a resume while the header (which reads from the last actual API response) still looked fine, and why the first message you sent immediately hit the limit again.

This affected fullscreen mode when compaction was auto-triggered by hitting the context limit. Manually running /compact was unaffected — those markers always saved.

After the fix: auto-compaction markers are saved to the session file, so a resumed session loads only what's after the most recent compaction.

For your specific session: your file analysis (4 markers, 14.5MB after the last one, post-region parentUuids pointing into the pre-region) is consistent with this — earlier compactions saved, later auto-compactions didn't, so the "last marker" is older than your last in-memory compaction. The stubbing experiment not changing the Messages count also fits: the loader was reading further back than the region you trimmed.

github-actions[bot] · 3 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.