Skip to content

Fable 5 falsely walled behind usage credits in interactive picker for Max accounts using a setup-token (headless -p works) #79597

Description

@AndrewLuebke

Summary

On a Max account authenticated with a claude setup-token (CLAUDE_CODE_OAUTH_TOKEN, headless/automation auth), the interactive model picker walls Fable 5 behind usage credits:

Fable 5 runs on usage credits, purchased separately from your plan. You don't have usage credits yet.

…even though the same account + same token grants Fable fine in headless (-p) mode, and claude.ai states Fable 5 is a standard part of the Max plan. The interactive picker appears to fail-closed because the setup-token's account profile doesn't include a plan tier (subscriptionType), so the client can't confirm the account is Max.

Environment

  • Claude Code 2.1.216 (latest; native installer, Linux/Debian 13)
  • Auth: claude setup-tokenCLAUDE_CODE_OAUTH_TOKEN (no credentials.json present)
  • Plan: Max (oauthAccount present, hasPrimaryApiKey: false, 0 approved API keys — subscription auth, not API billing)

Reproduction

  1. Authenticate a Max account via claude setup-token and run with CLAUDE_CODE_OAUTH_TOKEN set (no credentials.json on disk).
  2. In an interactive session, run /model and select Fable 5 — or launch with claude --model claude-fable-5.
  3. Observe the gate: "Fable 5 runs on usage credits… You don't have usage credits yet," offering only "Set up usage credits" or a fallback model (Sonnet 5 / keep current). Fable cannot be selected.

Expected

A Max account should be able to select Fable 5 interactively regardless of whether it authenticated via /login or a setup-token — consistent with headless behavior and with claude.ai's "Fable 5 is a standard part of your Max plan."

Evidence that the server does grant Fable to this account (only the interactive client walls it)

Headless request on the exact same token succeeds and is genuinely served by Fable:

echo hi | claude -p --model claude-fable-5 --output-format json | jq '{modelUsage: (.modelUsage|keys), is_error}'
{ "modelUsage": ["claude-fable-5", "claude-haiku-4-5-20251001"], "is_error": false }

No credits are consumed; is_error: false; claude-fable-5 is the serving model.

Likely root cause

Under a setup-token, ~/.claude.json oauthAccount has no subscriptionType field (only seatTier / userRateLimitTier / organizationRateLimitTier). The Fable credits gate appears to check the plan tier client-side and, unable to confirm Max, fail-closes to "credits required." Relevant cached flags:

  • tengu_saffron_credits_only_tiers: ["enterprise"] — Max is not a credits-only tier
  • tengu_saffron_lattice.planLimitsEndDate: 2026-07-20T07:00:00Z — the "included in plan limits" launch window closed, after which the client applies the credits gate

Because oauthAccount carries profileFetchedAt and is re-fetched from the server, the missing subscriptionType cannot be patched locally — the server profile for a setup-token simply omits it.

Suggested fix directions

  • Have the interactive Fable entitlement check fail-open (or resolve the tier server-side) when the local profile lacks subscriptionType but the account otherwise has access — matching what the headless path already does.
  • Or include subscriptionType in the account profile returned for setup-token auth.

Also (minor, same root cause family)

In-product /feedback submission returns HTTP 403 under the setup-token (couldn't file this in-product), which is why this is on GitHub. The setup-token appears to lack scope for the feedback endpoint as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions