CLAUDE_CODE_OAUTH_TOKEN from claude setup-token returns 401 Invalid bearer token on every API call

Status Open
Reported on v2.1.214
Maintainer reply None cached
Activity 2 comments · opened Aug 7, 2026

Bug report: CLAUDE_CODE_OAUTH_TOKEN from claude setup-token returns 401 Invalid bearer token on every API call

Summary

claude setup-token completes successfully and prints a long-lived OAuth token tied to my Claude subscription. Setting that token via the documented CLAUDE_CODE_OAUTH_TOKEN environment variable causes claude auth status to report a logged-in state, but every actual API call — including a minimal claude -p "..." headless call — fails immediately with:

API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"Invalid bearer token"}}

Environment

  • Claude Code CLI version: 2.1.214
  • Platform: macOS (MacBook Air)
  • Install path: ~/.local/bin/claude (only one CLI install on PATH — verified with which claude)
  • Plan: Claude Max (confirmed via account UI; regenerated the token after first accidentally authenticating setup-token against a different, non-Max account in the browser — the correct-account token still fails identically)
  • Auth method reported: claude auth status{"loggedIn": true, "authMethod": "oauth_token", "apiProvider": "firstParty"}

Steps to reproduce

  1. claude setup-token — completes, prints "Long-lived authentication token created successfully!" and a token.
  2. Copy the token via pbpaste directly to a file (bypassing any terminal/editor paste step) to rule out transcription error.
  3. export CLAUDE_CODE_OAUTH_TOKEN=$(cat <token-file>)
  4. claude auth status → reports loggedIn: true.
  5. claude -p "Reply with exactly the two words: token works" → fails with 401 Invalid bearer token.

Debug evidence

Ran with -d api --debug-file, in a plain terminal with no parent Claude Code process involved. Redacted excerpt:

[DEBUG] Policy limits: fetch failed (auth 401) — Request failed with status code 401
[ERROR] API error (attempt 1/11): 401 {"type":"error","error":{"type":"authentication_error","message":"Invalid bearer token"},"request_id":"req_011CdovoWAFBoeptebW8T1x9"}
[ERROR] API error (attempt 2/11): 401 {"type":"error","error":{"type":"authentication_error","message":"Invalid bearer token"},"request_id":"req_011CdovoZhpUuevZmB1qqPn6"}
[ERROR] Error in API request: 401 {"type":"error","error":{"type":"authentication_error","message":"Invalid bearer token"},"request_id":"req_011CdovoZhpUuevZmB1qqPn6"}
[ERROR] API auth_error: Invalid bearer token

Two concrete request_id values from failed calls, for server-side log lookup:

  • req_011CdovoWAFBoeptebW8T1x9
  • req_011CdovoZhpUuevZmB1qqPn6

(A separate, nested test run from inside an active Claude Code session additionally surfaced SDK getOAuthToken callback failed: Tool permission stream closed before response received — that specific error is believed to be an artifact of the nested-session test setup, not the root cause, since it does not appear in the plain-terminal reproduction above, which fails with a clean, direct 401 with no internal SDK complication.)

What has been ruled out, each with a direct test

  • Copy/paste corruption — token saved via pbpaste directly to a file with no editor involved; confirmed single-line, plausible length (127 bytes), no embedded line breaks.
  • Conflicting environment variablesenv | grep -i anthropic shows nothing set except CLAUDE_CODE_OAUTH_TOKEN itself; no ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN.
  • apiKeyHelper override — not configured in any settings file.
  • Binary/version mismatchwhich claude and claude --version confirm a single install used throughout, both when generating the token and when testing it.
  • System clock skew — local clock reads correctly, no evidence of drift.
  • Sandbox/permission-prompt configuration — reproduced identically with all local sandbox restrictions fully disabled; this is a pure client/server auth failure, unrelated to local tool permissions.
  • Wrong account — first token was generated against the wrong (non-Max) browser session and discarded; regenerated against the correct Max-plan account with an identical result.

Related existing report

This matches the symptom described in issue #48996 ("401 Invalid Bearer Token Immediately After Successful Login") — closed as "not planned" with no resolution, and notably described there as machine- or account-instance-specific rather than account-wide (a colleague on the same organization account, different machine, had no issue). This report adds a second, independently reproduced, more thoroughly eliminated case of what looks like the same underlying defect, via the setup-token / CLAUDE_CODE_OAUTH_TOKEN path specifically rather than interactive /login.

Impact

This blocks the documented, intended use case for CLAUDE_CODE_OAUTH_TOKEN — authenticating headless/automated Claude Code runs (e.g., via cron or launchd) against a Pro/Max subscription rather than separate API-key billing. Right now there appears to be no working path to unattended, subscription-billed Claude Code execution on this machine.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗