[Bug] `claude-opus-5` absent from client model table on 2.1.212 — /context uses a 200K denominator while auto-compact and the API both use 1M

Status Fixed / completed
Reported on v2.1.212
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 30, 2026 · closed Aug 20, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

TL;DR

On Claude Code 2.1.212, the string claude-opus-5 does not appear anywhere in the client binary — zero occurrences, while every sibling model (opus-4-6, opus-4-7, opus-4-8, fable-5, sonnet-5, haiku-4-5) is present dozens of times. With autoCompactWindowsCache: null in ~/.claude.json, the client has no window definition for the model and /context falls back to a 200,000 denominator.

The interesting part is that this is not a coherent 200K session. In the same client, at the same moment:

| Layer | Window in effect for claude-opus-5 |
|---|---|
| /context gauge + per-category breakdown | 200,000 ❌ |
| Auto-compact trigger | ~1,000,000 ✅ |
| API (server) | ~1,000,000 ✅ |

So the client disagrees with itself. The gauge reads 671.4k/200k (336%) and urges /compact, while the same client happily lets the session keep running because its compaction logic uses the real 1M window.

This reconciles #81693 and #82226, which currently describe opposite behaviors. I have hard evidence for #81693's symptom and hard evidence against #82226's premise on this account — see Evidence 4.

The actionable harm is the false compaction prompt: the UI tells the user their context is 336% full and to compact now. Obeying it discards ~630K tokens of live working context that fit comfortably in the real window.

---

Environment

| | |
|---|---|
| Claude Code | 2.1.212 (native install, commit 8b2783a8f907) |
| Platform | linux-x64 — Ubuntu 24.04.4 LTS on WSL2 (kernel 6.6.87.2-microsoft-standard-WSL2) |
| Entrypoint | CLI, fullscreen TUI |
| Provider | Claude subscription via OAuth — no ANTHROPIC_BASE_URL, no Bedrock/Vertex/gateway |
| Plan | Max |
| Model | claude-opus-5, set via ~/.claude/settings.json → "model": "claude-opus-5" |
| Effort | high |
| Overrides | None. No managed settings; ANTHROPIC_MODEL, ANTHROPIC_DEFAULT_OPUS_MODEL, CLAUDE_CODE_SUBAGENT_MODEL, availableModels, enforceAvailableModels, fallbackModel all unset |

Relevant: claude doctor reports Last update attempt: failed (install_failed) — 2026-07-30. This install is pinned to a binary built before Opus 5 shipped, which is likely why the failure mode here is "model unknown → fallback constant" rather than the "model known but mis-flagged" variant described in #82226.

Dataset backing the numbers below: 7,379 claude-opus-5 assistant requests across 290 session transcripts.

---

Evidence 1 — the gauge

/context on a live session, model claude-opus-5:

claude-opus-5
671.4k/200k tokens (336%)

Estimated usage by category
  System prompt:   3.1k tokens  (1.5%)
  System tools:   23.5k tokens (11.8%)
  MCP tools:       4.0k tokens  (2.0%)
  Custom agents:   1.5k tokens  (0.8%)
  Memory files:    6.0k tokens  (3.0%)
  Skills:          2.2k tokens  (1.1%)
  Messages:      159.8k tokens (79.9%)

Suggestions
  ⚠ Context is 336% full
    Autocompact will trigger soon, which discards older messages.
    Use /compact now to control what gets kept.

The 671.4k numerator is correct — it matches the last recorded request in that session's transcript exactly (671,373 = input_tokens + cache_read_input_tokens + cache_creation_input_tokens). Only the denominator is wrong.

Evidence 2 — the breakdown is derived from the bad denominator, not measured

3.1 + 23.5 + 4.0 + 1.5 + 6.0 + 2.2 + 159.8 = 200.1k

The categories sum to exactly 200K. Messages: 159.8k is not a measurement — it is 200K minus the overhead rows. Actual message content in that session is ~631K tokens. Every per-category figure and percentage in /context is unreliable while the window constant is wrong, which matters because this panel is the primary tool users have for diagnosing context bloat.

Evidence 3 — same session, model switch isolates the variable

The session in Evidence 1 ran 330 main-loop requests entirely under claude-opus-4-8, growing to 671,373 tokens with a correct gauge and no false compaction warning. Switching the active model to claude-opus-5 — with zero requests issued under the new model, so the conversation is byte-identical — immediately produced the /200k (336%) display.

Same session, same context, same client process. Only the model id changed.

Evidence 4 — the server accepts ~945K on claude-opus-5 (contradicts #82226 here)

Largest prompt accepted per model across all recent transcripts:

| Model | Requests | Largest accepted prompt |
|---|---|---|
| claude-opus-4-8 | 4,593 | 995,851 |
| claude-opus-5 | 7,379 | 945,372 |
| claude-fable-5 | 4,994 | 835,965 |
| claude-sonnet-5 | 1,552 | 186,965 |

Zero Prompt is too long errors on claude-opus-5 at any size. A full-history scan surfaced exactly one such error ever: 2026-06-30, claude-opus-4-8, at a prior prompt size of 386,248 tokens, on an older client — nowhere near the 166K–178K band reported in #82226.

I want to be precise about scope: this does not disprove #82226. It shows the server-side rejection is not universal across accounts/versions, which is useful for triage — it suggests #82226 and #81693 may be two distinct defects that happen to share a symptom vocabulary, rather than one bug.

Evidence 5 — auto-compact uses the real 1M window, disagreeing with the gauge

Auto-compact events recorded in the transcripts:

{"type":"system","subtype":"compact_boundary","timestamp":"2026-07-28T12:05:34.569Z","version":"2.1.212",
 "compactMetadata":{"trigger":"auto","preTokens":946490,"postTokens":49476,
                    "cumulativeDroppedTokens":897014,"durationMs":188488}}

That is claude-opus-5, on this same 2.1.212 binary, auto-compacting at 946,490 tokens. The six requests immediately preceding it were all claude-opus-5 at 937K–945K, all successful. For comparison, claude-opus-4-8 auto-compacted at preTokens: 1,006,339.

So the compaction path resolves ~1M for a model the display path resolves as 200K. Two code paths, two different answers, same binary, same model id.

Corroborating this from the other direction: the live session in Evidence 1 is sitting at 671K and has not compacted. A genuine 200K limit would have compacted it around 190K, roughly half a million tokens ago.

Evidence 6 — the model id is absent from the client binary

$ D=~/.local/share/claude/versions/2.1.212
$ for m in claude-opus-4-6 claude-opus-4-7 claude-opus-4-8 claude-opus-5 \
           claude-fable-5 claude-sonnet-4-6 claude-sonnet-5 claude-haiku-4-5; do
    printf '%-22s %s\n' "$m" "$(LC_ALL=C grep -a -c -- "$m" "$D")"
  done

claude-opus-4-6        51
claude-opus-4-7        39
claude-opus-4-8        71
claude-opus-5           0     <-- absent
claude-fable-5         27
claude-sonnet-4-6      41
claude-sonnet-5        32
claude-haiku-4-5       43

Related observations in the same install:

  • ~/.claude.json → "autoCompactWindowsCache": null (verified null across five consecutive on-disk backups spanning ~30 minutes). If this is the server-fed per-model window table, it is empty.
  • "additionalModelOptionsCache" contains only {"value": "claude-fable-5[1m]", ...} — no Opus 5 entry.
  • The binary declares [1m] variants for claude-sonnet-4-6[1m], claude-sonnet-4-5-20250929[1m], claude-opus-4-7[1m], claude-opus-4-6[1m]. There is no claude-opus-5[1m].

Note this directly contradicts #82226's claim that "the client's built-in model table marks Opus 5 native_1m". On 2.1.212 there is no Opus 5 entry to mark. That is consistent with the two reports being version-dependent and possibly distinct defects.

---

Hypothesis (root cause)

claude-opus-5 shipped after this client build. Its context window must therefore arrive from the server, plausibly via autoCompactWindowsCache. That cache is null, so the display path has no entry and falls back to a hardcoded 200000 default, while the compaction path derives its limit from a different source that still resolves correctly.

Falsifiable predictions, in case they help triage:

  1. On a build where grep -c claude-opus-5 is non-zero, /context should show /1M.
  2. Populating autoCompactWindowsCache with an Opus 5 entry should fix the gauge without a client upgrade.
  3. If neither holds, the fallback constant is being applied somewhere upstream of the model table entirely.

Impact

  1. Data loss via false prompt. The UI states "Context is 336% full" and recommends /compact. Following that guidance discards ~630K tokens of working context that the real window holds fine. This is the concrete harm — the UI actively instructs the user to destroy their own session state.
  2. Under-use of paid context. Users who trust the gauge self-limit to ~200K on a 1M model, or compact 5× more often than necessary.
  3. /context is unusable for diagnosis. Because the per-category breakdown is normalized against the wrong denominator (Evidence 2), the panel meant to diagnose context bloat reports fabricated numbers.
  4. Silent trust erosion. The gauge and the compaction engine disagree, so the number on screen has no stable relationship to what the client will actually do.

Steps to reproduce

  1. Install Claude Code 2.1.212 (or any build predating Opus 5 — verify with grep -a -c claude-opus-5 <binary> returning 0).
  2. Confirm ~/.claude.json has "autoCompactWindowsCache": null.
  3. Run a session under claude-opus-4-8 and grow it past 200K tokens. Observe /context reports against a 1M denominator, correctly.
  4. Switch the active model to claude-opus-5 without sending a request.
  5. Run /context.

Expected vs actual

Expected: /context reports against ~1,000,000 for claude-opus-5, consistent with what the auto-compact path and the API both enforce. Per-category figures reflect measured content.

Actual: /context reports 671.4k/200k (336%), per-category figures are back-solved from a 200K total, and the user is advised to compact a session that is at ~67% of its real capacity.

Relation to #81693 and #82226

  • #81693 — same symptom (client reports 200K for Opus 5). This report adds: the likely mechanism (model id absent from the binary + empty window cache), proof that the per-category breakdown is corrupted by the same constant, and the observation that the compaction path is unaffected. Reported there on 2.1.216; reproduced here on 2.1.212, so the defect spans at least two builds.
  • #82226 — opposite premise (client optimistic at 1M, server enforcing ~200K). On this account and version the server accepts 945,372 tokens on claude-opus-5 with zero rejections in 7,379 requests, and the client's built-in table has no Opus 5 entry at all. Both of that issue's premises fail to reproduce here, which suggests these are two separate defects.

Happy to run additional read-only diagnostics on this install if it helps narrow it down.

View original on GitHub ↗

3 Comments

leandro849 · 2 months ago

Correction + stronger evidence

Two corrections to my own report, and one piece of evidence that is better than anything in the original post.

Correction 1 — I overstated the scope of "there is no claude-opus-5[1m]"

In Evidence 6 I wrote "There is no claude-opus-5[1m]" and used it to contradict #82226. That claim is only valid for the 2.1.212 binary. The variant clearly exists in the ecosystem — #82761 and #81025 both report running claude-opus-5[1m] on 2.1.220. I asserted a global absence from local evidence. Apologies to #82226; that part of my comparison was not sound.

Correction 2 — Evidence 6 is correlation, not proof of mechanism

I also undercut my own argument without noticing: claude-opus-4-8[1m] is likewise absent from the 2.1.212 binary (the only [1m] ids compiled in are sonnet-4-6, sonnet-4-5-20250929, opus-4-7, opus-4-6), yet Opus 4.8 resolves its 1M window correctly on this exact install. So "model id absent from the binary" cannot by itself be the mechanism — variant/window data evidently arrives from the server.

Evidence 6 should be read as a correlation worth checking, not as the root cause. The root-cause hypothesis I still consider most likely is the empty autoCompactWindowsCache combined with a display-path fallback constant.

New evidence — this rules out the "user picked the 200K variant" explanation

The obvious alternative reading of my report is user error: that "model": "claude-opus-5" (no suffix) selects a genuine 200K variant, and /context was simply telling the truth. I chased that hard, because it would have made this issue invalid.

It does not hold. ~/.claude.json → projects[].lastModelUsage preserves the [1m] suffix when one is in play, which makes it a reliable discriminator. On this install:

project A  ->  lastModelUsage key: "claude-opus-4-8[1m]"    <- suffix preserved
project B  ->  lastModelUsage key: "claude-opus-5"          <- no suffix
project C  ->  lastModelUsage key: "claude-opus-5"          <- no suffix

The session recorded under project B reached a 915,227-token prompt, accepted, with claude-opus-5 and no suffix. Project C's reached 571,611. Same discriminator that faithfully records [1m] for Opus 4.8 shows plain claude-opus-5 for sessions running 3–4.5× beyond a 200K window.

So the suffix-less claude-opus-5 is not a 200K model. The client is displaying a 200K denominator for a model that the server is serving at ~1M, which is the defect originally reported.

Net effect on the report

| Claim | Status |
|---|---|
| /context shows a 200K denominator for claude-opus-5 | holds |
| Per-category breakdown is back-solved from the wrong total (sums to exactly 200K) | holds |
| Server accepts ~945K on claude-opus-5; zero Prompt is too long in 7,379 requests | holds — now reinforced by the lastModelUsage discriminator |
| Auto-compact path resolves ~1M while the display path resolves 200K | holds |
| Model id absent from binary ⇒ root cause | downgraded to correlation |
| "There is no claude-opus-5[1m]" ⇒ contradicts #82226 | retracted — true only of 2.1.212 |

The user-facing harm is unchanged and is the part I would prioritize: the UI reports "Context is 336% full" and recommends /compact on a session sitting at roughly 67% of its real window. Acting on that advice discards ~630K tokens of live context.

If it is useful for triage, lastModelUsage may be a cheap way to distinguish the #81693 population from the #82226 population — whether the affected sessions were running the suffixed variant or the plain id.

bcherny collaborator · 1 month ago

Fixed in 2.1.219 — changelog: "Added Claude Opus 5 (claude-opus-5), now the default Opus model — 1M context, fast mode at $10/$50 per Mtok" (https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md). Closing — reply to reopen if it still happens on the latest version.

🤖 Generated with Claude Code

github-actions[bot] · 3 days 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.