[Bug] Claude Opus 5 context window size incorrectly reported as 200k instead of 1M tokens

Status Open
Reported on v2.1.216
Maintainer reply None cached
Activity 5 comments · opened Jul 27, 2026

Bug Description
Claude Code v2.1.216 reports context_window_size: 200000 for model claude-opus-5 (a 1M-context model), so the statusline context gauge saturates and /compact appears to do nothing. The statusline hook receives: "model": {"id": "claude-opus-5"}, "context_window": {"total_input_tokens": [REDACTED], "context_window_size": 200000, "used_percentage": 90} "exceeds_200k_tokens": [REDACTED] 179399/200000 = 90%, so the arithmetic is fine — the window constant is wrong. Evidence it is not an account cap: the SAME session file records main-loop requests of 1,211,454 prompt tokens under claude-opus-4-8 and 573,238 under claude-fable-5. Only claude-opus-5 is treated as 200k, so this looks like a missing model entry and is a regression vs opus-4-8 in the same session. Impact: sessions get context-pressured and compacted near 200k on a model that carries 1M (~5x under-use of paid context); post-compact the re-injected floor (file-history snapshots, agent listing, invoked-skill text, summary, deferred tool names — ~117k tokens measured here) is already ~59% of the believed window, so /compact never visibly lowers the gauge. It also breaks anything downstream that consumes used_percentage as an occupancy signal.

Environment Info

  • Platform: linux
  • Terminal: tmux
  • Version: 2.1.216
  • Feedback ID: 21185b29-66cf-4e01-8767-5538b4006a08

Errors

[]

View original on GitHub ↗

3 Comments

awaliuddin · 1 month ago

What happened

Claude Code v2.1.216 reports a 200,000-token context window for claude-opus-5, which has a 1M context window. Everything downstream of that constant is consequently wrong: the statusline context gauge saturates at 100% on long sessions, and /compact appears to have no effect.

Evidence

The JSON the statusline command receives on stdin (captured by teeing stdin in the configured statusLine script; unrelated fields removed):

{
  "model": { "id": "claude-opus-5", "display_name": "claude-opus-5" },
  "version": "2.1.216",
  "context_window": {
    "total_input_tokens": 179399,
    "context_window_size": 200000,
    "used_percentage": 90,
    "remaining_percentage": 10
  },
  "exceeds_200k_tokens": false
}

179399 / 200000 = 89.7% → 90, so the percentage math is self-consistent — only context_window_size is wrong. The sibling exceeds_200k_tokens field looks like related 200k-era plumbing.

This is not an account or transport limit

Parsing the same session transcript (~/.claude/projects/<project>/<session>.jsonl), main-loop rows only (isSidechain != true), taking usage.input_tokens + usage.cache_read_input_tokens + usage.cache_creation_input_tokens per request:

| model | requests | max prompt tokens observed |
|---|---:|---:|
| claude-opus-4-8 | 15,531 | 1,211,454 |
| claude-fable-5 | 2,230 | 573,238 |
| claude-opus-5 | 1,996 | 288,460 |

The same client, account and session file has carried 1.21M-token prompts under claude-opus-4-8. Only claude-opus-5 is treated as a 200k model, which suggests a missing or stale model entry rather than a deliberate limit — and makes this a regression relative to claude-opus-4-8.

Why /compact looks broken (probably the most user-visible symptom)

/compact compresses the conversation but does not reduce what is re-injected afterwards. Measured on one session after the last compact_boundary:

| re-injected after every compact | ≈ tokens |
|---|---:|
| file-history-snapshot × 2 | ~34k |
| agent_listing_delta (subagent catalog) | ~17k |
| invoked_skills (full text of every skill invoked earlier in the session) | ~7k |
| the compaction summary itself | ~5k |
| deferred_tools_delta (~200 tool names) | ~4k |
| project memory / instruction files | ~50k |
| floor | ~117k |

Against a true 1M window that floor is ~12%. Against the believed 200k it is ~59% before a single tool call, so one read-heavy turn puts the gauge back above 90% and /compact never appears to help.

Impact

  1. Sessions are context-pressured and compacted near 200k on a model that supports 1M — roughly 5× under-use of available context.
  2. Each unnecessary compaction loses continuity and re-pays cache-creation cost on the ~117k floor.
  3. The statusline gauge conveys no information once saturated, and anything consuming context_window.used_percentage as an occupancy signal (we use it as an input to an internal preflight check) gets a false "critical" reading permanently.

Expected

context_window.used_percentage should be computed against the effective context window actually in use for the current model. If the 1M window for claude-opus-5 requires a beta flag or tier that this session does not have, the client should still report the effective window it is operating with — and ideally surface which one it picked.

Reproduce

  1. Run Claude Code v2.1.216 with claude-opus-5.
  2. Configure a statusLine command that tees its stdin to a file, e.g. input=$(cat); printf '%s' "$input" > /tmp/statusline-input.json.
  3. Inspect .context_window.context_window_size in that file: 200000, with .model.id = claude-opus-5.
  4. Optional cross-check: sum input_tokens + cache_read_input_tokens + cache_creation_input_tokens per assistant message in the session transcript and compare per-model maxima.

Environment

  • Claude Code 2.1.216
  • model claude-opus-5, thinking enabled, effort high
  • Linux (WSL2), bash
awaliuddin · 1 month ago

_WORKAROUND:_ Apparently all you have to do is turn on /usage-credits then the (1M) context loads.

zcutlip · 1 month ago

This appears to to apply to Sonnet 5 as well.

Another workaround: append the [1m] tag to the model tags, even though this shouldn't be necessary.

Showing cached comments. Read the full discussion on GitHub ↗