[BUG] --model value is not verified before use

Status Open
Reported on v2.1.289
Maintainer reply None cached
Activity 0 comments · opened Oct 5, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code doesn't check the model name at startup, whether it comes from --model, ANTHROPIC_MODEL or "model" in settings. With a typo or a non-existent ID:

  • the interactive session starts with no warning
  • the welcome header and /status show the string as if it were a real, resolved model
  • the problem first appears after the user sends their first prompt

A typo in an alias (sonet instead of sonnet) in a shell alias, settings file or env var looks exactly like a working setup until then.

What Should Happen?

Free-form model strings must keep working (Bedrock/Vertex IDs, gateways behind ANTHROPIC_BASE_URL, models newer than the client), so this isn't a request for a hardcoded allowlist. Instead:

  1. On the first-party API, check the model at startup (in the background is fine). If it doesn't exist, show a warning right away and suggest the nearest alias (sonet → "did you mean sonnet?").
  2. Until a name is resolved or checked, mark it in the header and /status (e.g. sonet (unverified)) rather than formatting it like a real model.

Error Messages/Logs

From the launch with `--model totally-fake-model`:


[auto-mode] verifyAutoModeGateAccess: ... model=totally-fake-model modelSupported=true ...
[API:timing] dispatching to firstParty model=totally-fake-model
[API REQUEST] /v1/messages ...                  <- first time the model is checked
[ERROR] API error (attempt 1/11): 404 404 {"type":"error","error":{"type":"not_found_error","message":"model: totally-fake-model"},"request_id":"req_011CfdPgpsjhbJmsiH
F2AJ4B"}
[WARN] Streaming endpoint returned 404, falling back to non-streaming mode
[API REQUEST] /v1/messages ...                  <- second request, same bad model
[ERROR] Non-streaming fallback also failed: 404 {... "request_id":"req_011CfdPgsFrf9XHBr6BztkAA"}
[ERROR] API model not found: model: totally-fake-model

Related bug visible here: a model-not-found 404 is read as a streaming-endpoint problem, so every prompt is followed by a non-streaming retry that is certain to fail a
s well.

Steps to Reproduce

  1. claude --model sonet (also: claude --model claude-opus-9-9, claude --model totally-fake-model)
  2. Look at the welcome header, then run /status
  3. Send any prompt

Actual

Header, no warning:

▝▜██████▀  sonet with xhigh effort · Claude Team
▝▜██████▀  claude-opus-9-9 · Claude Team
▝▜██████▀  totally-fake-model with xhigh effort · Claude Team

/status → Model: sonet

For comparison, a valid alias gets a display name (header Opus 5.5 · Claude Team) and /status shows how it resolved (Model: opus (claude-opus-5-5)). An unknown s
tring passes through as raw text with nothing to mark it.

Capability logic also runs against the unknown name. The configured effortLevel (xhigh) is applied and shown ("sonet with xhigh effort"), claude-opus-9-9 gets a
different effort (high) than other unknown names, and auto mode reports modelSupported=true (see log).

Only after the first prompt:

⏺ There's an issue with the selected model (sonet). It may not exist or you may not have access to it.
  Run /model to pick a different model.

Claude Model

Other

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.289

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

Reproduces on both zsh and tmux.

Print mode (-p):

$ claude -p --model totally-fake-model "reply with OK"
[claude-code:unrecognized_model] {"model":"totally-fake-model","query_source":"sdk"}    <- stderr
There's an issue with the selected model (totally-fake-model). It may not exist or you may not have access to it. Run --model to pick a different model.
# exit code 1

Exiting with code 1 is correct, but:

  • an internal tag ([claude-code:unrecognized_model] {...}) leaks to stderr
  • "Run --model to pick a different model": --model is a flag, not a command
  • --output-format json returns "subtype":"success" together with "is_error":true

The same happens with ANTHROPIC_MODEL=... and --settings '{"model":"..."}'.

View original on GitHub ↗