You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug: OAuth auth + cache_control ephemeral causes HTTP 400 on all Claude models since 2026-03-17 #17910
All Claude models fail with HTTP 400 when using OAuth authentication (Claude subscription). The error started on 2026-03-17 with no configuration changes. Non-Anthropic models (e.g., GPT-5-nano) work fine.
Root Cause
OpenCode's bundled @ai-sdk/anthropic unconditionally injects cache_control: {"type": "ephemeral"} into system message blocks. This prompt caching metadata appears to no longer be accepted on the OAuth authentication path (Claude subscription). Previously, the Anthropic API silently ignored this field for OAuth requests; as of 2026-03-17, it returns HTTP 400.
No thinking parameter is present — this is not a thinking/extended-thinking issue.
The API response is {"type":"error","error":{"type":"invalid_request_error","message":"Error"}} with status 400.
Confirmed: not a version-specific regression
Tested on both v1.2.27 and v1.2.26 — same error. The cache_control: {"type": "ephemeral"} injection is hardcoded in the bundled @ai-sdk/anthropic (applyCaching()), so downgrading does not help.
Steps to Reproduce
Authenticate via OAuth (opencode providers login anthropic)
Run opencode run "say hello" --model anthropic/claude-sonnet-4-6
→ HTTP 400 invalid_request_error
Works fine with API key authentication or non-Anthropic providers.
Expected Fix
When the authentication method is OAuth (Claude subscription), strip cache_control from system blocks before sending to the Anthropic API. Prompt caching is an API-tier feature and should not be applied to OAuth-authenticated requests.
This issue might be a duplicate of existing issues. Please check:
Broken Claude Max #7410: Broken Claude Max — an existing open issue tracking Claude OAuth/subscription failures that may cover the same breakage
If this is a distinct root cause (specifically the cache_control: ephemeral injection being newly rejected on the OAuth path), it may warrant staying open as a separate, more precise bug report. Please check #7410 to confirm.
#7410 is about Anthropic blocking non-Claude Code clients via system prompt pattern matching (e.g., rejecting requests that contain "opencode" in the system message). The workaround there is injecting "You are Claude Code" into the system prompt.
System prompt content triggers client identity check
cache_control: {"type": "ephemeral"} in system blocks triggers invalid_request_error
Error pattern
Credential authorization error ("only for Claude Code")
Generic HTTP 400 invalid_request_error with "message": "Error"
Workaround
Inject "You are Claude Code" into system prompt
Unknown — cache_control is hardcoded in applyCaching()
Affected scope
OAuth users without opencode-anthropic-auth
OAuth users withopencode-anthropic-auth@0.0.13 already installed and working
Timing
Recurring since Jan 2026
Started specifically on 2026-03-17 (worked on 2026-03-16)
Key evidence
opencode-anthropic-auth is active and has been working — the system prompt already contains "You are Claude Code". This is not a client identity rejection.
The only anomaly in the request is cache_control: {"type": "ephemeral"} on system blocks, which is injected by the bundled @ai-sdk/anthropic's applyCaching() and cannot be disabled by plugins.
It's possible that Anthropic expanded their OAuth restrictions to reject cache_control (prompt caching is an API-tier feature). But the mechanism and fix path are different from #7410.
Investigation Update: Root cause is not cache_control
After building from source with a fix that strips cache_control from OAuth requests, the ephemeral metadata was successfully removed from the request body — confirmed via logs. However, the API still returns HTTP 400.
Direct API testing
Tested the Anthropic API directly with the stored OAuth access token:
With Authorization: Bearer header:
HTTP 401 — {"type":"error","error":{"type":"authentication_error","message":"OAuth authentication is currently not supported."}}
With x-api-key header (how @ai-sdk/anthropic actually sends it):
Both paths fail even with a minimal request (model + max_tokens + single user message, no cache_control, no thinking, no tools).
Conclusion
The root cause is notcache_control: {"type": "ephemeral"}. The Anthropic API appears to have dropped OAuth token support as of 2026-03-17. The vague "message":"Error" response on the x-api-key path is because an OAuth token is not a valid API key.
This may be an intentional change on Anthropic's side, or a regression in their OAuth infrastructure. Either way, the fix needs to come from the Anthropic API or from how OpenCode's plugin auth layer handles OAuth tokens for the Anthropic provider.
Environment
Tested on: OpenCode built from source (dev branch + cache_control fix)
cache_control stripping — I built from source with cache_control removed from OAuth requests. The field was successfully stripped (confirmed via request logging), but the API still returned HTTP 400.
Direct API testing — Minimal curl requests with only an OAuth token and a simple prompt also failed, ruling out any SDK-level issue.
x-api-key path — Using the OAuth token as an API key returns a generic "message": "Error", which is expected since OAuth tokens are not API keys.
So the root cause is confirmed: Anthropic now requires x-anthropic-billing-header validation for OAuth sessions, as @HCPTangHY pointed out via the clewdr fix.
Workaround remains API Key authentication for now:
opencode providers login -p anthropic
# Select "Manually enter API Key"
I'll leave it to the maintainers to decide the path forward regarding the billing header requirement.
@rekram1-node Can you elaborate please?
I think most are interested to know if there is a plan to have this fixed anytime or the team/owner has any concerns.
Thanks
Customer-terms
Section 2 (prohibiting sharing of credentials) and Section 3.7 (prohibiting automated access of non-API Keys) have covered relevant restrictions
Activity
github-actions commentedon Mar 17, 2026
This issue might be a duplicate of existing issues. Please check:
If this is a distinct root cause (specifically the
cache_control: ephemeralinjection being newly rejected on the OAuth path), it may warrant staying open as a separate, more precise bug report. Please check #7410 to confirm.cyberprophet commentedon Mar 17, 2026
Difference from #7410
#7410 is about Anthropic blocking non-Claude Code clients via system prompt pattern matching (e.g., rejecting requests that contain "opencode" in the system message). The workaround there is injecting
"You are Claude Code"into the system prompt.This issue is mechanistically different:
cache_control: {"type": "ephemeral"}in system blocks triggersinvalid_request_errorinvalid_request_errorwith"message": "Error"cache_controlis hardcoded inapplyCaching()opencode-anthropic-authopencode-anthropic-auth@0.0.13already installed and workingKey evidence
opencode-anthropic-authis active and has been working — the system prompt already contains"You are Claude Code". This is not a client identity rejection.thinkingparameter — this rules out the thinking/ephemeral conflict described in bug: Claude Sonnet 4.5 with thinking + ephemeral cache returns HTTP 400 #17883.cache_control: {"type": "ephemeral"}on system blocks, which is injected by the bundled@ai-sdk/anthropic'sapplyCaching()and cannot be disabled by plugins.It's possible that Anthropic expanded their OAuth restrictions to reject
cache_control(prompt caching is an API-tier feature). But the mechanism and fix path are different from #7410.fix: skip prompt caching for OAuth-authenticated Anthropic requests
cyberprophet commentedon Mar 17, 2026
Investigation Update: Root cause is not
cache_controlAfter building from source with a fix that strips
cache_controlfrom OAuth requests, theephemeralmetadata was successfully removed from the request body — confirmed via logs. However, the API still returns HTTP 400.Direct API testing
Tested the Anthropic API directly with the stored OAuth access token:
With
Authorization: Bearerheader:With
x-api-keyheader (how@ai-sdk/anthropicactually sends it):Both paths fail even with a minimal request (
model+max_tokens+ single user message, nocache_control, nothinking, no tools).Conclusion
The root cause is not
cache_control: {"type": "ephemeral"}. The Anthropic API appears to have dropped OAuth token support as of 2026-03-17. The vague"message":"Error"response on thex-api-keypath is because an OAuth token is not a valid API key.This may be an intentional change on Anthropic's side, or a regression in their OAuth infrastructure. Either way, the fix needs to come from the Anthropic API or from how OpenCode's plugin auth layer handles OAuth tokens for the Anthropic provider.
Environment
type: "oauth"inauth.json)HCPTangHY commentedon Mar 17, 2026
Xerxes-2/clewdr@a4e5df3
This commit fixed this issue. To put it simply, Anthropic added some new checks for the user-agent and salt values.
R00tedbrain commentedon Mar 19, 2026
@HCPTangHY how fix now ? my error?
fix(oauth): add Claude Code user-agent to token exchange and refresh …
jwcrystal commentedon Mar 20, 2026
Root Cause Update
Per @cyberprophet's further investigation, the issue is not just about
cache_control:cache_controlstripped, API still returns HTTP 400x-api-keypath returns vague"message": "Error"because OAuth token is not a valid API keyThe Real Fix
As noted by @HCPTangHY, the actual fix is in clewdr@a4e5df3:
Anthropic added new validation checks for
x-anthropic-billing-header.The fix requires:
Generate a billing header with format:
The header includes a SHA256 hash based on:
SALT+ sampled characters from user message +VERSIONPrepend this as a system block to requests
This essentially mimics Claude Code's billing/authentication flow that Anthropic now requires for OAuth sessions.
Workaround
Until OpenCode implements the billing header, use API Key authentication:
opencode providers login -p anthropic # Select "Manually enter API Key"Get your API Key from Anthropic Console.
Note on PR #18311
PR #18311 addresses the
cache_controlissue but does not include thex-anthropic-billing-headerfix. A more comprehensive fix is needed.cyberprophet commentedon Mar 20, 2026
Thanks @jwcrystal for the clean summary.
To clarify the timeline from my side:
cache_controlstripping — I built from source withcache_controlremoved from OAuth requests. The field was successfully stripped (confirmed via request logging), but the API still returned HTTP 400.curlrequests with only an OAuth token and a simple prompt also failed, ruling out any SDK-level issue.x-api-keypath — Using the OAuth token as an API key returns a generic"message": "Error", which is expected since OAuth tokens are not API keys.So the root cause is confirmed: Anthropic now requires
x-anthropic-billing-headervalidation for OAuth sessions, as @HCPTangHY pointed out via the clewdr fix.Workaround remains API Key authentication for now:
opencode providers login -p anthropic # Select "Manually enter API Key"I'll leave it to the maintainers to decide the path forward regarding the billing header requirement.
quarryman commentedon Mar 22, 2026
Guys, can anyone elaborate? Is it just tecnical limitation easy to overcome by patching headers or there is something legal behind it?
jwcrystal commentedon Mar 24, 2026
quarryman commentedon Mar 24, 2026
@rekram1-node Can you elaborate please?
I think most are interested to know if there is a plan to have this fixed anytime or the team/owner has any concerns.
Thanks
r00tedbrain-backup commentedon Mar 24, 2026
-.-
rekram1-node commentedon Mar 26, 2026
anthropic has rquested that we do not engage w/ these and that we drop support for oauth entirely. We are required to do so for legal reasons
feat(providers): phase 02 03-openrouter — OpenRouter + router + gate …
feat(providers): phase 02 03-openrouter — OpenRouter + router + gate …