From ac87eb0eaee1d786e15d8fe12f8a87b43b05ef37 Mon Sep 17 00:00:00 2001 From: Amitesh Gupta Date: Sat, 4 Jul 2026 17:42:15 +0530 Subject: [PATCH] fix: address review feedback on PR #32103 Fixed both P1 edge cases Greptile flagged in _get_mock_response_content (empty choices list and None message content) by returning an empty string to still short-circuit rather than crashing or falling through to the real model, and added two regression tests covering them. --- .../messages/handler.py | 5 +- ...erimental_pass_through_messages_handler.py | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/litellm/llms/anthropic/experimental_pass_through/messages/handler.py b/litellm/llms/anthropic/experimental_pass_through/messages/handler.py index 24c82986fca..75134f393da 100644 --- a/litellm/llms/anthropic/experimental_pass_through/messages/handler.py +++ b/litellm/llms/anthropic/experimental_pass_through/messages/handler.py @@ -368,9 +368,12 @@ def _get_mock_response_content( if isinstance(mock_response, str): return mock_response if isinstance(mock_response, litellm.ModelResponse): + if not mock_response.choices: + return "" first_choice = mock_response.choices[0] if isinstance(first_choice, litellm.Choices): - return first_choice.message.content + return first_choice.message.content or "" + return "" return None diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py index 2e8fd6d18c0..f70b2542f22 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py @@ -676,6 +676,55 @@ def test_handler_short_circuits_on_model_response_mock_response(): assert result["content"][0]["text"] == "Blocked by guardrail" +def test_handler_short_circuits_on_model_response_with_empty_choices(): + """A ModelResponse mock with no choices must still short-circuit instead + of crashing on an unguarded choices[0] access.""" + from litellm.llms.anthropic.experimental_pass_through.messages import handler + + blocked_response = ModelResponse(choices=[], model="bedrock-guardrail") + + with patch.object( + handler.base_llm_http_handler, + "anthropic_messages_handler", + ) as mock_base_handler: + result = handler.anthropic_messages_handler( + max_tokens=10, + messages=[{"role": "user", "content": "some blocked content"}], + model="anthropic/claude-3-5-sonnet-20241022", + custom_llm_provider="anthropic", + mock_response=blocked_response, + ) + + mock_base_handler.assert_not_called() + assert result["content"][0]["text"] == "" + + +def test_handler_short_circuits_on_model_response_with_none_content(): + """A ModelResponse mock whose message content is None must still + short-circuit rather than silently falling through to the real model.""" + from litellm.llms.anthropic.experimental_pass_through.messages import handler + + blocked_response = ModelResponse( + choices=[Choices(message=Message(content=None))], + model="bedrock-guardrail", + ) + + with patch.object( + handler.base_llm_http_handler, + "anthropic_messages_handler", + ) as mock_base_handler: + result = handler.anthropic_messages_handler( + max_tokens=10, + messages=[{"role": "user", "content": "some blocked content"}], + model="anthropic/claude-3-5-sonnet-20241022", + custom_llm_provider="anthropic", + mock_response=blocked_response, + ) + + mock_base_handler.assert_not_called() + assert result["content"][0]["text"] == "" + + def test_presanitized_flag_not_leaked_to_provider_params(): """The private sentinel must be popped, never forwarded as a request param.""" from litellm.llms.anthropic.experimental_pass_through.messages import handler