Repository navigation
Description
Description
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.
Evidence from request body
{
"model": "claude-sonnet-4-6",
"max_tokens": 32000,
"stream": true,
"system": [
{ "type": "text", "text": "...", "cache_control": { "type": "ephemeral" } },
{ "type": "text", "text": "...", "cache_control": { "type": "ephemeral" } },
{ "type": "text", "text": "..." },
{ "type": "text", "text": "..." }
]
}- No
thinkingparameter 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.
Related
- [Question]: How does oh-my-opencode map the 'max' variant for native Anthropic provider models like claude-opus-4-6? code-yeongyu/oh-my-openagent#2630 — Same breakage reported on 2026-03-17, "was working on 2026-03-16, broke on 2026-03-17 with no config changes"
- bug: Claude Sonnet 4.5 with thinking + ephemeral cache returns HTTP 400 #17883 — Previously filed as thinking + ephemeral conflict, but the actual root cause is OAuth + ephemeral
- feat(provider): add adaptive thinking and 1M context support for Claude Opus 4.6 #12342 — Pending
@ai-sdk/anthropicv2→v3 upgrade PR
Environment
- OpenCode: v1.2.26, v1.2.27 (both affected)
- Auth: OAuth (Claude subscription)
- OS: Linux (WSL2)
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-auth[email protected]already 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 …