`claude setup-token` tokens rejected with "API Error: 400 status code (no body)" on first request — Max 20x account, fresh mints, reproduces locally and in CI

Status Open
Reported on v2.1.232
Maintainer reply None cached
Activity 3 comments · opened Aug 15, 2026

Summary

Every long-lived OAuth token minted by claude setup-token (correct sk-ant-oat01- prefix) is rejected by the API with API Error: 400 status code (no body) on the very first request — while interactive Claude Code on the same machine, same account, works perfectly. Reproduces identically in GitHub Actions (claude-code-action@v1, claude_code_oauth_token input) and locally (CLAUDE_CODE_OAUTH_TOKEN=<token> claude -p "..."). Multiple fresh mints over several hours on 2026-08-15 (~18:00–20:00 UTC) all fail the same way.

Environment

  • Account: Claude Max 20x (organizationType: claude_max, billingType: stripe_subscription, subscription active since 2026-02)
  • Local: Claude Code 2.1.232 on Windows 11 (Git Bash) — interactive use works
  • CI: ubuntu-latest, anthropics/claude-code-action@v1 (also reproduced with the CLI pinned to 2.1.232 via path_to_claude_code_executable)
  • Timing note: mints occurred hours after the Aug 14 20:00 – Aug 15 00:11 UTC OAuth incident on status.claude.com was marked resolved

Failure signature

{"type":"system","subtype":"init","message":"Claude Code initialized","model":"claude-sonnet-5"}
{"type":"result","subtype":"success","is_error":true,"duration_api_ms":0,"num_turns":1,
 "total_cost_usd":0,"input_tokens":0,"api_error_status":400,
 "result":"API Error: 400 status code (no body)"}

Assistant message model is <synthetic>, is_api_error_message: true, error: "unknown". Fails in ~250 ms at zero cost — the first request never gets a body back.

Ruled out (each tested)

  1. Token value corruption — token piped via stdin with CR/whitespace stripping; multiple careful re-pastes; same result.
  2. Wrong token type — confirmed sk-ant-oat01- prefix (not sk-ant-api03/sk-ant-sid01).
  3. CI environment — reproduces locally with only CLAUDE_CODE_OAUTH_TOKEN set; action debug logs show the token delivered to the execute phase, no Bedrock/Vertex/base-URL overrides, anthropic_api_key empty.
  4. Model — identical 400 with default claude-sonnet-5 and explicit --model claude-haiku-4-5-20251001.
  5. CLI version — identical 400 on 2.1.233 (CI default) and 2.1.232 (pinned; the exact version that works interactively on the same machine).
  6. Account mismatch — setup-token browser approval performed in the same claude.ai account the CLI is logged into (verified via oauthAccount metadata).
  7. Stale mint / revocation by newer mints — every attempt used the newest mint, pasted immediately.
  8. Workspace API-key policy (#54502) — not applicable; consumer claude_max org, the workspace setting does not exist.

Expected

A freshly minted setup-token token authenticates for user:inference on a Max account, as documented for CI use.

Possibly related

  • anthropics/claude-code-action#1316 (oat01 token 400s in action, works locally — our case fails in BOTH, so possibly a different or wider issue)
  • anthropics/claude-code-action#1281 (Max-plan OAuth token failures)
  • The Aug 14–15 OAuth incident — is token issuance fully recovered?

Ask

Is long-lived token issuance currently degraded for Max accounts, and is there server-side logging for the 400-no-body path that can identify what the request is missing?

View original on GitHub ↗

3 Comments

up2itnow0822 · 2 months ago

Update — error-layer calibration narrows this to request construction, not token validity:

  • Deliberately invalid token (CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-garbage claude -p "hi") → Failed to authenticate. API Error: 401 OAuth access token is invalid.
  • Freshly minted real token, same command → API Error: 400 status code (no body)

So freshly minted tokens are recognized as valid credentials (they do not hit the 401 invalid-token path) — the request built in env-token mode is then rejected with a bodyless 400 at some later validation layer. Interactive keychain auth on the same account/machine works, so whatever context the profile-aware path attaches (billing/beta headers?) appears to be missing or mismatched in the CLAUDE_CODE_OAUTH_TOKEN path.

Possibly relevant account detail: organizationType: claude_max, tier default_claude_max_20x, hasExtraUsageEnabled: true — if inference for extra-usage-enabled Max accounts requires billing context the env-token request path doesn't send, that would reproduce exactly this split (env-token 400 everywhere incl. CI; interactive fine).

Reproduced identically on 2.1.232 and 2.1.233 (local and CI, ubuntu-latest and Windows/Git Bash).

Sattvaai · 1 month ago

I can confirm this issue is still reproducible on Windows with a freshly generated long-lived OAuth token.

Environment

Claude Code: 2.1.252
Executable: C:\Users\AIWorkforceAgent\.local\bin\claude.exe
PowerShell: 5.1.26100.8875
OS: Microsoft Windows NT 10.0.26200.0
Authentication: freshly generated `claude setup-token`
Environment variable: `CLAUDE_CODE_OAUTH_TOKEN`

Reproduction

The token was generated successfully with:

claude setup-token

Claude Code reported:

Long-lived authentication token created successfully
OAuth token valid for 1 year

The actual OAuth token is not included here.

The token was then supplied to the Claude process through CLAUDE_CODE_OAUTH_TOKEN.

Minimal test:

claude -p "Reply exactly: CLAUDE_OAUTH_OK"

Result, consistently:

API Error: 400 status code (no body)

I also reproduced the same result when the environment variable was injected by a Windows launcher rather than set interactively.

Additional observations

  • This is a newly minted token, not an expired /login session.
  • Claude Code starts successfully and reaches the API request.
  • The failure is repeatable.
  • The token is passed without intentionally modifying its value.
  • Windows filesystem/ACL access to the credential is working.
  • No API key is being intentionally used instead of the OAuth token.
  • Repeated calls fail with the same HTTP 400 / no-body response.

This reproduction is on Claude Code 2.1.252, so the issue appears to persist beyond the 2.1.232/2.1.233 versions mentioned in the original report.

It would be useful if Claude Code could surface a request/correlation ID or the backend error body for this authentication failure so affected users can distinguish token-format, account-policy, and server-side issuance failures.

Sattvaai · 1 month ago

Additional diagnostic from my reproduction:

Claude Code: 2.1.252
OS: Windows NT 10.0.26200.0
PowerShell: 5.1.26100.8875

With the freshly generated CLAUDE_CODE_OAUTH_TOKEN injected:

claude auth status

returns:

{
  "loggedIn": true,
  "authMethod": "oauth_token",
  "apiProvider": "firstParty"
}

Without the injected token, the same machine returns:

{
  "loggedIn": false,
  "authMethod": "none",
  "apiProvider": "firstParty"
}

Therefore Claude Code is definitely detecting and selecting the long-lived OAuth token, and there is no competing stored login credential.

However:

claude -p "Reply exactly: CLAUDE_OAUTH_OK"

still returns:

API Error: 400 status code (no body)

This appears to narrow the failure to the request/backend path after OAuth-token selection rather than local credential discovery or precedence.

No OAuth token or other credential is included in this report.