TL;DR — Claude Code speaks Anthropic's dialect, including newer fields and experimental beta headers that only Anthropic's own API accepts. Point it at a proxy or a non-Anthropic model and the upstream rejects a field it has never seen — Unknown parameter: 'output_config' is the current face of this, and it is a whole family, not one bug. The fix is to strip or translate the unknown fields at the layer in between; the one place it cannot be fixed is Claude Code's own request body.
The error
HTTP 400
{"error": {"message": "Unknown parameter: 'output_config'.", "type": "invalid_request_error"}}
The tell is the timing: your setup worked, you changed ANTHROPIC_BASE_URL or the model name, and now every request 400s before the model is ever reached.
Why it happens
Claude Code is written against Anthropic's API and tracks it closely — including fields that are new, and beta features enabled through experimental headers. Anything sitting between Claude Code and a model has to accept that whole vocabulary.
Three ways that breaks:
- A proxy passes the body through unchanged to a model that does not know the field. LiteLLM in front of an OpenAI or Bedrock model is the usual case: the field is valid Anthropic, meaningless to the upstream, and gets rejected rather than dropped.
- The proxy's own validator rejects it. Some gateways validate against a schema they maintain; a field newer than the gateway's release is unknown to it and never reaches the model at all.
- Beta headers. Claude Code attaches experimental
anthropic-betaheaders for features it uses. Third-party endpoints — Bedrock, Vertex, proxy services — often reject requests carrying headers they do not implement, and the 400 names a parameter rather than the header, which sends you hunting in the wrong place.
The version coupling is the part worth internalising: Claude Code updates on its own schedule, so a setup that works today can break on a client update with no change on your side. This is not a one-time fix; it is a surface you either isolate or keep patching.
Where the fix can live
| Layer | What to do | Trade-off | |---|---|---| | The proxy | Strip or translate unknown fields before forwarding; keep the proxy current with the client | Correct place, but you own the maintenance forever | | Model choice | Point Claude Code at an actual Anthropic model through the proxy | Sidesteps the problem, gives up the model flexibility you wanted | | Pin the client | Hold Claude Code at a known-good version | Buys time, accrues debt, and you lose fixes | | ~~The client~~ | ~~Configure Claude Code to omit the field~~ | Not exposed — do not spend time looking for this setting |
If you are on LiteLLM, this class of failure is tracked in its issue tracker rather than its docs, which is exactly why the error feels undocumented: Claude Code fails with non-Anthropic models via LiteLLM Proxy.
Diagnosing which one you have
Send the same request without the proxy:
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{"model":"claude-sonnet-5","max_tokens":16,"messages":[{"role":"user","content":"ping"}]}'
- Works direct, fails through the proxy → the proxy or the upstream model. Check the proxy's request log for the exact rejected field; that name tells you whether it is cause 1 or 2.
- Fails both ways → auth or model access, not this.
Read the proxy's outbound log, not just the error returned to the client. The rejection usually happens upstream and the message you see has been relayed, sometimes with the original detail flattened.
Prevention
- Treat the client version as part of your configuration. Record which Claude Code version a proxy setup was verified against; upgrades are the most common cause of sudden 400s here.
- Log the full outbound body once when standing up a new endpoint. Ten seconds of reading beats an hour of guessing which field is unknown.
- Do not retry a 400. The request is malformed for that upstream and will be malformed on every attempt — see the other terminal errors in the LLM API error reference.
- If you would rather not own the translation layer, that is exactly what a router in front of the providers absorbs — what a router API should handle for you.
Part of the LLM API Error Reference — errors indexed by their exact strings.