From fb753f003da3fef563f0063ef7a0adcea8db71e4 Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Sat, 31 Oct 2026 04:27:55 -0700 Subject: [PATCH] fix(anthropic): keep the request out of deliberate translation 400s on Claude routes A BadRequestError raised by the shared message translation already names its problem, so it no longer carries every message as Received Messages. A 700 KB text attachment with an unsupported charset otherwise answered a 700 KB 400, and redacting that text held the event loop for about 40 s through the proxy. --- litellm/llms/anthropic/chat/transformation.py | 2 ++ .../test_anthropic_chat_transformation.py | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/litellm/llms/anthropic/chat/transformation.py b/litellm/llms/anthropic/chat/transformation.py index f03004cec15..295526ef9c5 100644 --- a/litellm/llms/anthropic/chat/transformation.py +++ b/litellm/llms/anthropic/chat/transformation.py @@ -2384,6 +2384,8 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): llm_provider=self._resolved_provider, drop_params=drop_params, ) + except litellm.BadRequestError as e: + raise AnthropicError(status_code=400, message=str(e)) except Exception as e: raise AnthropicError( status_code=400, diff --git a/tests/unit/llms/anthropic/chat/test_anthropic_chat_transformation.py b/tests/unit/llms/anthropic/chat/test_anthropic_chat_transformation.py index c8a2f783809..8b84c42dc4d 100644 --- a/tests/unit/llms/anthropic/chat/test_anthropic_chat_transformation.py +++ b/tests/unit/llms/anthropic/chat/test_anthropic_chat_transformation.py @@ -1,3 +1,4 @@ +import base64 import copy import json import logging @@ -10103,3 +10104,27 @@ def test_claude_cache_control_cap_does_not_count_a_message_level_hint_that_list_ assert sorted(_cached_texts(body)) == ["system prompt", "turn 1", "turn 2", "turn 3"] assert json.dumps(body).count('"cache_control"') == 4 + + +def test_completion_rejecting_a_text_attachment_does_not_echo_the_request_back(respx_mock: respx.MockRouter): + route: Final = respx_mock.post("https://api.anthropic.com/v1/messages").mock(return_value=httpx.Response(500)) + attachment_data: Final = base64.b64encode(b"attachment body that stays out of the error " * 64).decode() + + with pytest.raises(litellm.BadRequestError) as exc_info: + litellm.completion( + model="anthropic/claude-sonnet-4-5-20250929", + api_key="mock_api_key", + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "Summarize this file"}, + {"type": "file", "file": {"file_data": f"data:text/plain;charset=punycode;base64,{attachment_data}"}}, + ], + } + ], + ) + + assert "unsupported encoding: punycode" in str(exc_info.value) + assert attachment_data not in str(exc_info.value) + assert route.call_count == 0