[BUG] Fable 5 gated behind "Requires usage credits" under CLAUDE_CODE_OAUTH_TOKEN auth — client discards subscriptionType it already has

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 3 comments · opened Jul 26, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

When Claude Code authenticates via the CLAUDE_CODE_OAUTH_TOKEN environment variable (e.g. a long-lived token from claude setup-token), the /model picker gates Fable 5 behind "· Requires usage credits" even though:

  • the token belongs to a Max 5x account whose plan includes Fable 5,
  • the same account on the same machine shows Fable as included when using normal keychain login (claude auth login),
  • the API itself happily serves Fable to this exact token: CLAUDE_CODE_OAUTH_TOKEN=... claude --model fable -p "hi" works.

So the gating is purely client-side and contradicts both the account's actual entitlement and the server's behavior.

Root cause (from reading the 2.1.220 bundle): when the token comes from the env var, the credential object is built with the plan metadata hardcoded to null:

if (env.CLAUDE_CODE_OAUTH_TOKEN) return {
  accessToken: ..., refreshToken: null, expiresAt: null,
  scopes: [...],                                            // defaults to ["user:inference"]
  subscriptionType: env.CLAUDE_CODE_SUBSCRIPTION_TYPE || null,
  rateLimitTier: env.CLAUDE_CODE_RATE_LIMIT_TIER || null
};

subscriptionType: null then flows into the plan checks and the feature-flag user context (which omits subscriptionType/rateLimitTier when null), so the model picker treats the session as unknown-plan and falls into the credits-required branch — even though the cached oauthAccount in the config dir's .claude.json says organizationType: "claude_max" from a successful profile fetch. The client has the entitlement data; the picker just doesn't consult it in env-token mode.

Setting the (undocumented) overrides CLAUDE_CODE_SUBSCRIPTION_TYPE=max and CLAUDE_CODE_RATE_LIMIT_TIER=default_claude_max_5x fixes the picker, which confirms the mechanism.

What Should Happen?

With CLAUDE_CODE_OAUTH_TOKEN auth, Claude Code should resolve the plan from the cached oauthAccount profile (or re-fetch it) instead of assuming "no plan", so Fable 5 shows as included for accounts whose plan includes it — matching what the server actually serves and what keychain login shows for the same account.

If env-token sessions are intentionally excluded from subscription model entitlements, the picker message should say that ("not available with long-lived token auth — run /login") rather than the misleading "Requires usage credits", and CLAUDE_CODE_SUBSCRIPTION_TYPE / CLAUDE_CODE_RATE_LIMIT_TIER should be documented.

Error Messages/Logs

# /model picker entry under CLAUDE_CODE_OAUTH_TOKEN auth:
#   Fable  Fable 5 · Most capable for your hardest and longest-running tasks · Requires usage credits
# Same account via keychain login: no "Requires usage credits" suffix, Fable selectable.

Steps to Reproduce

  1. On a Max account, mint a long-lived token: claude setup-token.
  2. In a fresh shell: export CLAUDE_CODE_OAUTH_TOKEN=<token> (optionally a dedicated CLAUDE_CONFIG_DIR that has completed onboarding with this account).
  3. Run claude, open /model → Fable 5 shows "· Requires usage credits" / selection is gated.
  4. Exit; run CLAUDE_CODE_OAUTH_TOKEN=<token> claude --model fable -p "reply ok" → succeeds, proving the token is entitled to Fable server-side.
  5. Re-run step 3 with CLAUDE_CODE_SUBSCRIPTION_TYPE=max CLAUDE_CODE_RATE_LIMIT_TIER=default_claude_max_5x also exported → Fable shows as included.

Reproduced with two different accounts (Max 5x personal, Team with Fable) on the same machine; both are gated under env-token auth and fine under keychain login (CLI or macOS app).

Claude Model

Other (Fable 5)

Is this a regression?

I don't know

Claude Code Version

2.1.220 (Claude Code)

Platform

Anthropic API (claude.ai subscription auth)

Operating System

macOS

Terminal/Shell

Other (kitty)

Additional Information

Related but distinct: #80749, #79337, #79341, #79576 all report Fable credits-gating under normal keychain login (intermittent / server-side flag causes). This report is deterministic and specific to CLAUDE_CODE_OAUTH_TOKEN auth: the client discards plan metadata it already has. Use case: running two subscriptions side by side via per-account long-lived tokens injected through the env var.

View original on GitHub ↗

3 Comments

junxie6 · 2 months ago

I have a Claude Max plan and use both the Claude Code CLI and the Claude Code extension in VS Code on a headless server with an OAuth token. Here is how I got both approaches working.

First, reset ~/.claude.json and ~/.claude/settings.json:

cat > ~/.claude.json << 'EOF'
{
  "hasCompletedOnboarding": true
}
EOF
cat > ~/.claude/settings.json << 'EOF'
{
  "model": "claude-fable-5",
  "effortLevel": "xhigh",
  "theme": "light"
}
EOF

Next, reset ~/.claude/.credentials.json:

cat > ~/.claude/.credentials.json << 'EOF'
{
  "claudeAiOauth": {
    "accessToken": "sk-ant-oat01-*****",
    "refreshToken": "",
    "expiresAt": 9999999999999,
    "scopes": [
      "user:file_upload",
      "user:inference",
      "user:mcp_servers",
      "user:profile",
      "user:sessions:claude_code"
    ],
    "subscriptionType": "max",
    "rateLimitTier": "default_claude_max_5x"
  },
  "organizationUuid": ""
}
EOF

Replace the value of the accessToken field with the token generated by:

claude setup-token

It is okay to leave the organizationUuid field empty.

Next, unset the following Claude Code-related environment variables:

unset CLAUDE_CODE_OAUTH_TOKEN
unset CLAUDE_CODE_SUBSCRIPTION_TYPE
unset CLAUDE_CODE_RATE_LIMIT_TIER

Also, make sure these variables are either removed from or commented out in ~/.bashrc.

You can check for them by running:

grep CLAUDE_CODE_ ~/.bashrc

Then completely close VS Code.

Kill the VS Code Server process. This step is important:

sudo pkill -f vscode-server

Reopen VS Code and start a new Claude Code session.

Finally, run:

/usage

You should see something similar to:

Auth method: Claude API
Plan: Claude Max
Edvins-MT · 1 month ago

Still present in 2.1.246 (Linux, Fedora 44).

  • Auth via CLAUDE_CODE_OAUTH_TOKEN (freshly minted with claude setup-token minutes before — rules out the expired-token case from #85204): selecting Fable 5 shows the usage-credits gate. On my Team/Enterprise account the dialog variant is "You don't have usage credits yet. 1. Request usage credits from your admin / 2. Switch to Sonnet 5".
  • Same account, same machine, env -u CLAUDE_CODE_OAUTH_TOKEN claude + /login: Fable 5 available, no gate.
  • No [1m] model alias in settings (#79337 ruled out).

Feedback ID: c8ef6386-97b9-4977-9814-866410dd3680

anhtr · 1 month ago

Datapoint from a different trigger: the same wording appears under normal keychain login (no CLAUDE_CODE_OAUTH_TOKEN) on a Claude Enterprise seat, 2.1.259, macOS, VS Code extension. /model fable fell back to claude-fable-5 with "Draws from usage credits" - but metering demonstrably goes to plan pools: between two cachedUsageUtilization fetches ~15 minutes apart spanning only Fable 5 activity, session 28→34 %, weekly (all models) 54→55 %, weekly Fable-scoped 4→5 %, while extra_usage.used_credits stayed at 0 cents. additionalModelCostsCache is {} even immediately after logout/login on a fresh credential, so on this account the label cannot be coming from the null-subscriptionType path described above - possibly the same display fallback with a different cause (empty per-model cost cache). Full context: #91885.