fix(bedrock): strip output_config from Bedrock Invoke requests (#23042)

* fix(bedrock): strip output_config from Bedrock Invoke requests

Bedrock Invoke API does not support the output_config parameter
(added to Anthropic Messages API). Requests with output_config cause
400 errors: 'extraneous key [output_config] is not permitted'.

Strip output_config in both Bedrock Invoke transformation layers
(messages and chat), consistent with how output_format is already
handled and how VertexAI strips both parameters.

Fixes: https://github.com/BerriAI/litellm/issues/22797

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(bedrock): add output_config test for chat/invoke path

Addresses review feedback — the chat/invoke_transformations path now has
symmetric test coverage matching the messages/invoke_transformations path.

Fixes: https://github.com/BerriAI/litellm/issues/22797

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: giulio-leone <6887247+giulio-leone@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Giulio Leone 2026-03-08 04:33:53 +01:00 • committed by GitHub
parent e156507ca7
commit 1c3787264b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 108 additions and 0 deletions

View file

@ -108,6 +108,9 @@ class AmazonAnthropicClaudeConfig(AmazonInvokeConfig, AnthropicConfig):
_anthropic_request.pop("stream", None)
# Bedrock Invoke doesn't support output_format parameter
_anthropic_request.pop("output_format", None)
# Bedrock Invoke doesn't support output_config parameter
# Fixes: https://github.com/BerriAI/litellm/issues/22797
_anthropic_request.pop("output_config", None)
if "anthropic_version" not in _anthropic_request:
_anthropic_request["anthropic_version"] = self.anthropic_version

View file

@ -419,6 +419,10 @@ class AmazonAnthropicClaudeMessagesConfig(
anthropic_messages_request=anthropic_messages_request,
)
# 5b. Strip `output_config` — Bedrock Invoke doesn't support it
# Fixes: https://github.com/BerriAI/litellm/issues/22797
anthropic_messages_request.pop("output_config", None)
# 5a. Remove `custom` field from tools (Bedrock doesn't support it)
# Claude Code sends `custom: {defer_loading: true}` on tool definitions,
# which causes Bedrock to reject the request with "Extra inputs are not permitted"

View file

@ -386,6 +386,40 @@ def test_opus_4_5_model_detection():
# f"computer-use beta should be kept, got: {anthropic_beta}"
def test_output_config_removed_from_bedrock_chat_invoke_request():
"""
Test that output_config parameter is stripped from Bedrock Chat Invoke requests.
Bedrock Invoke API doesn't support the output_config parameter (Anthropic-only).
Ensures the chat/invoke path mirrors the messages/invoke path fix.
Fixes: https://github.com/BerriAI/litellm/issues/22797
"""
config = AmazonAnthropicClaudeConfig()
messages = [{"role": "user", "content": "test"}]
# Inject output_config into optional_params (simulates Anthropic SDK forwarding it)
optional_params = {
"max_tokens": 100,
"output_config": {"effort": "high"},
}
result = config.transform_request(
model="anthropic.claude-sonnet-4-20250514-v1:0",
messages=messages,
optional_params=optional_params,
litellm_params={},
headers={},
)
assert "output_config" not in result, (
f"output_config should be stripped for Bedrock Chat Invoke, got keys: {list(result.keys())}"
)
# Verify normal params survive
assert result["max_tokens"] == 100
def test_output_format_removed_from_bedrock_invoke_request():
"""
Test that output_format parameter is removed from Bedrock Invoke requests.

View file

@ -275,3 +275,70 @@ def test_remove_scope_from_cache_control():
# Verify scope is removed from messages
assert "scope" not in request["messages"][0]["content"][0]["cache_control"]
assert request["messages"][0]["content"][0]["cache_control"]["type"] == "ephemeral"
def test_bedrock_messages_strips_output_config():
"""
Ensure output_config is stripped from the request before sending to
Bedrock Invoke, which doesn't support this Anthropic-specific parameter.
Regression test for: https://github.com/BerriAI/litellm/issues/22797
"""
from litellm.types.router import GenericLiteLLMParams
cfg = AmazonAnthropicClaudeMessagesConfig()
messages = [{"role": "user", "content": [{"type": "text", "text": "Hello"}]}]
optional_params = {
"max_tokens": 4096,
"output_config": {
"effort": "high",
},
}
result = cfg.transform_anthropic_messages_request(
model="anthropic.claude-3-haiku-20240307-v1:0",
messages=messages,
anthropic_messages_optional_request_params=optional_params,
litellm_params=GenericLiteLLMParams(),
headers={},
)
assert "output_config" not in result, (
"output_config should be stripped — Bedrock Invoke rejects it"
)
# Other params should be preserved
assert result.get("max_tokens") == 4096
def test_bedrock_messages_strips_output_config_with_output_format():
"""
When both output_config and output_format are present, both should be
stripped (output_format is converted to inline schema, output_config
is simply dropped).
"""
from litellm.types.router import GenericLiteLLMParams
cfg = AmazonAnthropicClaudeMessagesConfig()
messages = [{"role": "user", "content": [{"type": "text", "text": "Hello"}]}]
optional_params = {
"max_tokens": 4096,
"output_config": {"effort": "low"},
"output_format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {"answer": {"type": "string"}},
},
},
}
result = cfg.transform_anthropic_messages_request(
model="anthropic.claude-3-haiku-20240307-v1:0",
messages=messages,
anthropic_messages_optional_request_params=optional_params,
litellm_params=GenericLiteLLMParams(),
headers={},
)
assert "output_config" not in result
assert "output_format" not in result