Setup-token auth silently downgrades Fable 5 to Sonnet 5 (subscriptionType missing from token profile) — forces fleets back onto fragile stored /login auth
What happened
On Claude Code 2.1.221 (and every version back through at least 2.1.219), a session authenticated with a long-lived claude setup-token on a Claude Max account cannot use Fable 5 — and the failure mode is a silent model downgrade:
- Session boots normally, statusline shows
Fable 5. - First inference renders "Switched to Sonnet 5 for this session · Fable 5 requires usage credits · /model to change" and the reply comes from Sonnet 5.
- No error, no exit code, no loud signal. The session keeps running on the wrong model.
The same account via stored /login auth runs Fable 5 perfectly — the subscription genuinely grants it (unified rate-limit headers confirm subscription billing on token sessions too). The client is fail-closing because the setup-token's oauthAccount profile omits subscriptionType, so the client treats a fully-entitled Max account as unsubscribed for model gating.
Reproduced today (2026-08-04) on a clean scratch CLAUDE_CONFIG_DIR:
claude setup-token # on a Claude Max account
CLAUDE_CODE_OAUTH_TOKEN=<token> claude --model claude-fable-5
# boots showing Fable 5 → first message silently answers on Sonnet 5
Related: #79597 (open since 2026-07-20, no maintainer response), #80484, #79441. Filing separately because the impact deserves its own report.
Why this is a big deal (customer impact)
I run a fleet of 8 machines with multiple Max accounts doing real production work. Because of this one missing field, every Fable session on every machine had to abandon the documented long-lived-token flow and fall back to stored /login credentials — which have their own long-standing unfixed problem (single-use rotating refresh token in a shared credentials file with no locking; #24317, closed without fix; concurrent sessions race the rotation and get randomly logged out).
To keep Fable usable at fleet scale we have had to build, ourselves:
- a per-machine credentials renewal broker (cron + file locking + proactive token rotation),
- neutered credential snapshots so short-lived workers can't consume the refresh rotation,
- auth-loss detection and self-healing for sessions that lose the rotation race,
- monthly manual browser re-login sittings across ~7 accounts × 8 machines as grants hard-expire,
- and model-drift detection, because the silent downgrade meant our highest-judgment automation ran on the wrong model for ~7 hours before anyone noticed.
That is an enormous amount of architecture a paying customer had to build and now maintain around what looks like a one-field fix on your side. I want to be direct: this is deeply frustrating, it has cost real engineering days, and it needs to be fixed.
Suggested fix (either side of it works)
- Server: populate
subscriptionTypein the profile returned for setup-token auth — the server already knows the subscription (it grants the model and bills it as subscription). - Client: when
subscriptionTypeis absent, do not fail-closed on model gating — trust the server's actual grant (attempt the call; the server is the authority). - At absolute minimum: make the downgrade loud — a hard error or an explicit opt-in flag — never a silent mid-session model swap. Silent model substitution is the worst possible failure mode for anyone running automation.
Environment
- Claude Code 2.1.221 (native installer), Ubuntu WSL2 on Windows 11
- Claude Max (verified
subscriptionType: maxviaclaude auth status --jsonon the same account's stored login) - Auth:
claude setup-token→CLAUDE_CODE_OAUTH_TOKEN
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗