Claude Code's Silent Feature Downgrade for Unrecognized Model IDs
When Claude Code cannot parse a model ID string, it silently disables advanced capabilities like effort and extended thinking, assumes a 200K context window with early compression, and switches to a shorter system prompt — requiring explicit configuration via modelOverrides, capability declarations, or version suffixes to restore full functionality.
Core Mechanism: One String Controls Six Client‑Side Decisions
In Claude Code the model identifier is not just a label sent to the provider. The client uses that single string to decide at least six behaviours:
Whether effort and extended thinking are available
Context window size and compression threshold
Which system prompt version (long or short) is used
Automatic model switching after a refusal
Allow‑list matching
Display name and diagnostic line in the model selector
If the ID string does not match a known Anthropic model pattern (e.g. claude-opus-4-7, us.anthropic.claude-opus-4-8-v1:0, or a @YYYYMMDD / [1m] suffix that can be stripped), Claude Code treats the model as unrecognized . The request still succeeds — the provider receives the original ID and responds normally — but the client silently changes its local judgements.
Four ID Shapes, Four Different "Unrecognized" Meanings
1. Provider‑style IDs containing an Anthropic model ID
Examples: us.anthropic.claude-opus-4-8-v1:0 (Bedrock), claude-opus-4-8@20250101 (Vertex). Because the Anthropic ID is embedded, Claude Code parses it and treats the model as recognized. All six judgements follow the known model.
2. Bedrock Application Inference Profile ARNs
This is the most nuanced case. The ARN is resolved to the underlying base model for request shape selection (via bedrock:GetInferenceProfile), so the wire protocol is correct. However, for capabilities and context window the documentation explicitly lists the ARN under "Not recognized" unless a modelOverrides entry maps its model to the ARN. The diagnostic line is also suppressed for resolvable ARNs. Result: request works, but effort/thinking stay off and the window defaults to 200K.
3. Azure Foundry Deployment Names
The model-config page states: "Claude Code never recognizes a pinned ID there, mapped or not". Yet the dedicated Foundry page gives two escape hatches: name the deployment with the Anthropic model ID (e.g. claude-opus-4-8) or add a modelOverrides mapping. When the deployment name contains the model ID, the diagnostic line is not written and the model gets the 1M window (for Fable, Sonnet 5+, Opus 4.7+). The two pages conflict on the word "never"; the Foundry‑specific page governs window and capabilities.
4. Pure Gateway Aliases (via ANTHROPIC_BASE_URL )
Claude Code sees only the alias. It assumes a 200K window (or 1M if the ID carries a [1m] suffix). Capabilities require modelOverrides mapping the Anthropic ID to the alias. Notably, the request fields ( effort, adaptive reasoning, context management) are still sent — unlike provider configurations where an unrecognized ID drops those fields entirely.
Declaring Capabilities: _SUPPORTED_CAPABILITIES (Provider Configs Only)
Environment variables ANTHROPIC_DEFAULT_*_MODEL_SUPPORTED_CAPABILITIES accept a comma‑separated list from six tokens: effort, xhigh_effort, max_effort, thinking, adaptive_thinking, interleaved_thinking. Critical: the variable replaces the entire capability table — omitted tokens are disabled. Writing only effort turns off thinking and the other four. The variable works only for the four provider configurations ( CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX, CLAUDE_CODE_USE_FOUNDRY, CLAUDE_CODE_USE_MANTLE); it has no effect behind an ANTHROPIC_BASE_URL gateway.
Mapping the Alias to a Known Model: modelOverrides and behavesAs
modelOverridesis a JSON object in the settings file where the key is the Anthropic model ID and the value is your provider name (e.g. {"claude-opus-4-7": "opus-prod"}). Reversing the direction is silently ignored. Since 2.1.200 this mapping also applies to IDs passed directly via --model or the ANTHROPIC_DEFAULT_*_MODEL variables. modelPicker.behavesAs (2.1.257+) sits on a selector row and borrows the capabilities and effort defaults of a known model ID while leaving the label and the wire‑protocol ID unchanged.
Context Window: Four Remedies, Each with Conditions
Upgrade Claude Code — newer versions recognise newer models. Stable channel may lag behind latest.
Map the name via modelOverrides or behavesAs.
Append [1m] to the model variable; the suffix is stripped before sending. Warning: the suffix is read per variable, not per model.
Set CLAUDE_CODE_MAX_CONTEXT_TOKENS — but its effect depends on ID shape:
Unrecognized, non‑ claude-, no [1m]: takes effect immediately.
Unrecognized with [1m]: 1M wins; must also set CLAUDE_CODE_DISABLE_1M_CONTEXT=1.
Recognized or claude- without strippable suffix: only works with DISABLE_COMPACT (disables all compression).
An additional escape hatch CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT=1 (2.1.223+) defers compression to the server, at the cost of one failed request; it does not trigger if the gateway rewrites the error.
Observability: Where the Silent Signals Live
Startup warning :
⚠ Model "my-gateway-opus" isn't recognized · context assumed to be 200k tokens. Disappears once the ID is recognised or a window is declared.
Diagnostic line (since 2.1.233):
[claude-code:unrecognized_model] {"model":"my-proxy-model","query_source":"sdk"}. Written once per model string per process. In non‑interactive mode ( -p) it goes to stderr for every --output-format; in interactive/background sessions it goes to ~/.claude/debug/<session-id>.txt with --debug.
Coverage gaps : the line is not written for resolvable provider IDs, resolvable Bedrock ARNs, Foundry names containing a Claude model ID, or malformed ARNs. Absence of the line does not mean nothing was lost.
Version 2.1.312 Changes: Prompt Version, Not Capability Table
2.1.312 switched Bedrock, Vertex, Foundry, and Mantle to the shorter system prompt for unrecognized names (custom deployment names, inference profile ARNs) even when they front Sonnet or Haiku. The toggle CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=0 forces the long prompt. This affects tool description verbosity only — tools, hooks, MCP, CLAUDE.md discovery are unchanged. The same release expanded automatic refusal fallback to cover unrecognized names, but the fallback still requires both the target model and the fallback model to be resolvable in your deployment.
Three‑Step Triage Checklist
Inspect the ID shape : Does it contain claude- + version? Is it a Bedrock ARN? A Foundry deployment name? A gateway alias?
Capture runtime signals :
claude -p "hi" --output-format json > out.json 2> err.log
grep '^\[claude-code:unrecognized_model\]' err.log | sed 's/^\[claude-code:unrecognized_model\] //' | jq -c '[.model, .query_source]'For interactive sessions:
grep -c unrecognized_model ~/.claude/debug/<session-id>.txt.
Verify window and capabilities : check /context or /autocompact for compression point (200K vs ~967K), and /effort for xhigh / max availability.
Matching Symptoms to Fixes
No diagnostic line, window as expected → ID already recognised; do nothing. Adding a capability table here would shrink the table.
Diagnostic line present, /effort works, compression at ~200K → only window missing. Use [1m], mapping, or window declaration. Do not add a capability table — it would disable default features.
Diagnostic line present, /effort unavailable → both capabilities and window missing. Apply mapping or capability table + window declaration.
No diagnostic line but /effort unavailable → model likely doesn't support effort, or a previous capability declaration omitted it. Re‑adding mapping won't help.
What This Is Not
Not a permission, sandbox, or network change.
Not universal — provider‑style IDs with embedded Anthropic IDs work fine; ARNs resolve for request shape; Foundry has documented workarounds.
Not a mandatory checklist — the documentation provides explicit overrides assuming you know what the backend supports. No client‑side validation is performed; mismatched declarations fall back to the highest supported tier (for effort) or are simply trusted.
The real takeaway: pinning a version (routing/billing) and declaring capabilities (client‑side behaviour) are two separate decisions that often happen in the same rename. Putting both in one change request lets reviewers see all six judgement rows; pinning only the name fixes routing but leaves the client silently downgraded.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architecture Development Notes
Focused on architecture design, technology trend analysis, and practical development experience sharing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
