anthropics / anthropics/claude-code

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

Open
#81,350 3 comments 4 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

### 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:

```js
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

```shell
# /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=` (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= 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.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the 2.1.220 bundle's CLAUDE_CODE_OAUTH_TOKEN credential construction and trace how subscriptionType reaches the /model picker and feature-flag user context. Inspect the cached oauthAccount in .claude.json and reproduce with the documented environment variables; done means an entitled Fable account is shown as included under token auth, or the picker gives an accurate limitation message.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
authentication, authorization, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.