Skip to content

fix: Anthropic OAuth sends empty X-Api-Key, misclassifies billing error - #6854

Closed
babinc wants to merge 3 commits into
NousResearch:mainfrom
babinc:fix/anthropic-oauth-billing-6475
Closed

fix: Anthropic OAuth sends empty X-Api-Key, misclassifies billing error#6854
babinc wants to merge 3 commits into
NousResearch:mainfrom
babinc:fix/anthropic-oauth-billing-6475

Conversation

@babinc

@babinc babinc commented Apr 9, 2026

Copy link
Copy Markdown

Summary

Fixes #6475 — "You're out of extra usage" error when using Claude Code OAuth tokens with the Anthropic provider.

1. Empty X-Api-Key header sent alongside OAuth Bearer auth (anthropic_adapter.py)

When ANTHROPIC_API_KEY= (empty) is set in .env (common after setup), the Anthropic Python SDK reads it from the environment and sends both X-Api-Key: (empty) and Authorization: Bearer <token> headers. The SDK's auth_headers property merges _api_key_auth (which returns {"X-Api-Key": ""} for empty string, since it only skips on None) with _bearer_auth. The empty X-Api-Key may cause Anthropic's server to route the request incorrectly.

Fix: Explicitly pass api_key=None to the SDK constructor and set client.api_key = None after construction for all auth_token paths, preventing the SDK from reading the empty env var.

2. "out of extra usage" not recognized as billing error (error_classifier.py)

The Anthropic error message "You're out of extra usage" was not matched by any pattern in _BILLING_PATTERNS. It fell through to format_error, which:

  • Triggered the immediate-abort is_client_error path (no retries, no backoff)
  • Skipped credential rotation and fallback provider attempts
  • Showed misleading diagnostics

Fix: Add "out of extra usage" to _BILLING_PATTERNS.

3. Beta header cleanup (anthropic_adapter.py)

  • Remove fine-grained-tool-streaming-2025-05-14 — does not exist in Claude Code v2.1.81 (zero matches in cli.js)
  • Add context-1m-2025-08-07 to _OAUTH_ONLY_BETAS — enables 1M context window for Opus 4.6 / Sonnet 4.6 (per Anthropic docs embedded in Claude Code)
  • Fix User-Agent header case: "user-agent""User-Agent" — the SDK sets "User-Agent": "Anthropic/Python X.X.X" in default_headers, and lowercase "user-agent" in _custom_headers doesn't replace it in the Python dict. httpx.Headers then concatenates both values (Anthropic/Python 0.93.0, claude-cli/2.1.81 (external, cli)) instead of overriding. Using the same case ensures proper replacement.

Note on the underlying error

These fixes improve error handling and header correctness. However, the HTTP 400 "out of extra usage" error from Anthropic may still occur for OAuth subscription tokens used from the Python SDK. During investigation we confirmed:

  • The OAuth token is valid (same token works in active Claude Code sessions)
  • Headers, betas, user-agent, and request body match Claude Code's format
  • The Python SDK still sends x-stainless-lang: python / x-stainless-runtime: CPython telemetry headers that differ from Claude Code's Node.js SDK

The exact server-side cause is unknown — it may be related to client fingerprinting, separate usage pools, or billing routing. Users who hit this consistently can use a direct Anthropic API key (sk-ant-api*) as a workaround.

Test plan

  • test_error_classifier.py — 88 tests pass
  • test_anthropic_adapter.py — 116 tests pass (2 updated for new betas/api_key behavior)
  • test_fallback_model.py, test_provider_fallback.py, test_anthropic_error_handling.py — 47 tests pass
  • Verified client.api_key is None when using OAuth auth
  • Verified X-Api-Key header is not sent when using Bearer auth
  • Verified wire-level User-Agent is claude-cli/X.X.X (external, cli) without Anthropic/Python prefix

🤖 Generated with Claude Code

babinc and others added 3 commits April 9, 2026 18:32
… billing error (#6475)

Two fixes for the "You're out of extra usage" error when using Claude Code
OAuth tokens with the Anthropic provider:

1. **Empty X-Api-Key header override (anthropic_adapter.py)**:
   When ANTHROPIC_API_KEY="" is set in .env (common after setup), the
   Anthropic Python SDK reads it from the environment and sends an empty
   X-Api-Key header alongside the valid Bearer Authorization header.
   The empty X-Api-Key may cause Anthropic's server to route the request
   through API-key auth instead of OAuth subscription auth, resulting in
   a billing error. Fix: explicitly set client.api_key = None after
   construction when using auth_token (Bearer) auth.

2. **Billing pattern not recognized (error_classifier.py)**:
   The error message "out of extra usage" was not matched by any billing
   pattern, causing it to be classified as format_error. This triggered
   the immediate-abort path instead of proper billing error handling
   (credential rotation, fallback attempts, correct error messaging).
   Fix: add "out of extra usage" to _BILLING_PATTERNS.

Also fixes beta headers:
- Remove non-existent "fine-grained-tool-streaming-2025-05-14" beta
- Add "context-1m-2025-08-07" beta (required for 1M context models)
- Fix User-Agent header case to properly override SDK default

Closes #6475

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove assertion for removed fine-grained-tool-streaming beta
- Add assertion for new context-1m-2025-08-07 beta
- Update api_key assertions: now explicitly None (not absent) for
  auth_token paths to prevent SDK env var fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@babinc babinc closed this by deleting the head repository Apr 10, 2026
CybercodeXx pushed a commit to CybercodeXx/hermes-agent that referenced this pull request Apr 17, 2026
… beta, tool names

- api_key=None in Bearer/OAuth paths: prevents SDK from reading
  ANTHROPIC_API_KEY env var and sending a conflicting X-Api-Key header
  alongside Authorization: Bearer, which caused auth rejections (NousResearch#6475)
- Defensive client.api_key = None post-construction for the same reason
- Add context-1m-2025-08-07 to _OAUTH_ONLY_BETAS (1M context for Claude Max)
- Fix User-Agent header capitalization in OAuth path
- Add "out of extra usage" to billing error patterns
- Rename session_search → search_sessions and skill_manage → manage_skills
  in prompt guidance strings to match actual tool names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CybercodeXx pushed a commit to CybercodeXx/hermes-agent that referenced this pull request Apr 17, 2026
The beta causes two failures:
  1. HTTP 429 "Extra usage is required for long context requests" with
     claude-sonnet-4-6 — the beta activates extended-context billing even
     for normal-size requests under Claude Max OAuth
  2. HTTP 400 "This authentication style is incompatible with the long
     context beta header" with claude-haiku-4-5 — model does not support it

Keeping the rest of PR NousResearch#6854: api_key=None fix, User-Agent header,
out-of-extra-usage error pattern, and tool name corrections.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Anthropic Claude subscription auth returns 'You're out of extra usage' in Hermes even after restart/re-login

1 participant