From 04ff660276b40da2c2e8e136b63a115672845c44 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Sat, 25 Oct 2025 16:55:16 -0700 Subject: [PATCH] fixes exception handling --- litellm/proxy/common_request_processing.py | 10 +++ .../test_llm_pass_through_endpoints.py | 76 +++++++++++++------ 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/litellm/proxy/common_request_processing.py b/litellm/proxy/common_request_processing.py index 3d13cc5135..108bb39501 100644 --- a/litellm/proxy/common_request_processing.py +++ b/litellm/proxy/common_request_processing.py @@ -740,6 +740,16 @@ class ProxyBaseLLMRequestProcessing: code=getattr(e, "status_code", status.HTTP_400_BAD_REQUEST), headers=headers, ) + elif isinstance(e, httpx.HTTPStatusError): + # Handle httpx.HTTPStatusError - extract actual error from response + # This matches the original behavior before the refactor in commit 511d435f6f + error_body = await e.response.aread() + error_text = error_body.decode("utf-8") + + raise HTTPException( + status_code=e.response.status_code, + detail={"error": error_text}, + ) error_msg = f"{str(e)}" raise ProxyException( message=getattr(e, "message", error_msg), diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py b/tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py index 06e8a3ce6a..84e53a903a 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py @@ -1105,15 +1105,6 @@ class TestBedrockLLMProxyRoute: handle_bedrock_passthrough_router_model, ) - mock_request = Mock() - mock_request.method = "POST" - mock_request.headers = {"content-type": "application/json"} - mock_request.query_params = {} - - mock_request_body = { - "messages": [{"role": "user", "content": [{"textaaa": "Hello"}]}] - } - bedrock_error_message = '{"message":"ContentBlock object at messages.0.content.0 must set one of the following keys: text, image, toolUse, toolResult, document, video."}' # Create a mock httpx.Response for the error @@ -1130,27 +1121,62 @@ class TestBedrockLLMProxyRoute: response=mock_error_response, ) + # Create mocks for all required parameters + mock_request = MagicMock(spec=Request) + mock_request.method = "POST" + mock_request.headers = {"content-type": "application/json"} + mock_request.query_params = {} + mock_request.url = MagicMock() + mock_request.url.path = "/bedrock/model/test-model/converse" + + mock_request_body = { + "messages": [{"role": "user", "content": [{"textaaa": "Hello"}]}] + } + mock_llm_router = Mock() - mock_llm_router.allm_passthrough_route = AsyncMock(side_effect=mock_http_error) + + # Mock ProxyBaseLLMRequestProcessing to raise the httpx error + with patch( + "litellm.proxy.common_request_processing.ProxyBaseLLMRequestProcessing.base_passthrough_process_llm_request", + new_callable=AsyncMock, + side_effect=mock_http_error + ): + mock_user_api_key_dict = Mock() + mock_user_api_key_dict.api_key = "test-key" + mock_user_api_key_dict.allowed_model_region = None + + mock_proxy_logging_obj = Mock() + mock_proxy_logging_obj.post_call_failure_hook = AsyncMock() - endpoint = "model/test-model/converse" - model = "test-model" + endpoint = "model/test-model/converse" + model = "test-model" - with pytest.raises(HTTPException) as exc_info: - await handle_bedrock_passthrough_router_model( - model=model, - endpoint=endpoint, - request=mock_request, - request_body=mock_request_body, - llm_router=mock_llm_router, + with pytest.raises(HTTPException) as exc_info: + await handle_bedrock_passthrough_router_model( + model=model, + endpoint=endpoint, + request=mock_request, + request_body=mock_request_body, + llm_router=mock_llm_router, + user_api_key_dict=mock_user_api_key_dict, + proxy_logging_obj=mock_proxy_logging_obj, + general_settings={}, + proxy_config=None, + select_data_generator=None, + user_model=None, + user_temperature=None, + user_request_timeout=None, + user_max_tokens=None, + user_api_base=None, + version=None, + ) + + assert exc_info.value.status_code == 400 + assert ( + "ContentBlock object at messages.0.content.0 must set one of the following keys" + in str(exc_info.value.detail) ) - assert exc_info.value.status_code == 400 - assert ( - "ContentBlock object at messages.0.content.0 must set one of the following keys" - in str(exc_info.value.detail) - ) - class TestLLMPassthroughFactoryProxyRoute: @pytest.mark.asyncio