From 1c3787264bf183d63de887abf445fae300ab79c7 Mon Sep 17 00:00:00 2001 From: Giulio Leone Date: Sun, 8 Mar 2026 04:33:53 +0100 Subject: [PATCH] fix(bedrock): strip output_config from Bedrock Invoke requests (#23042) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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> --- .../anthropic_claude3_transformation.py | 3 + .../anthropic_claude3_transformation.py | 4 ++ ...ations_anthropic_claude3_transformation.py | 34 ++++++++++ .../test_anthropic_claude3_transformation.py | 67 +++++++++++++++++++ 4 files changed, 108 insertions(+) diff --git a/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py b/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py index e5698843e8f..328c3a0b977 100644 --- a/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py @@ -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 diff --git a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py index 9fae5fd2a17..b11215e7f6b 100644 --- a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py @@ -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" diff --git a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py index d2fb45643de..cb05531c2f8 100644 --- a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py @@ -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. diff --git a/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py b/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py index e0b06ced172..f69f478278f 100644 --- a/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py +++ b/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py @@ -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