fix: propagate upstream status code in proxy API exception handler (#29402)

* fix: propagate upstream status code in proxy API exception handler

When Google GenAI / Vertex returns a 404 for deprecated or missing
models via streamGenerateContent, the exception was falling through to
a generic handler that defaulted to 500. Now provider exceptions
carrying a valid HTTP status_code correctly propagate it through to
the ProxyException.

* fix: apply black formatting to common_request_processing.py

* fix: tighten status code range to 400-599 and deduplicate ProxyException raise
This commit is contained in:
Tyson Cung 2026-06-09 20:11:24 +08:00 • committed by Sameer Kankute
parent 31240b5d90
commit 5845dde4aa
No known key found for this signature in database
2 changed files with 45 additions and 1 deletions

View file

@ -1949,12 +1949,26 @@ class ProxyBaseLLMRequestProcessing:
code=status.HTTP_400_BAD_REQUEST,
headers=headers,
)
# Extract status_code from the exception if it carries one.
# Provider exceptions (NotFoundError, BadRequestError, GeminiError,
# VertexAIError, etc.) all have a status_code attribute reflecting
# the upstream API response. Use it to return the correct HTTP code
# instead of defaulting to 500.
_exc_status_code = getattr(e, "status_code", None)
if (
_exc_status_code is not None
and isinstance(_exc_status_code, int)
and 400 <= _exc_status_code <= 599
):
_code = _exc_status_code
else:
_code = status.HTTP_500_INTERNAL_SERVER_ERROR
raise ProxyException(
message=getattr(e, "message", error_msg),
type=getattr(e, "type", "None"),
param=getattr(e, "param", "None"),
openai_code=getattr(e, "code", None),
code=getattr(e, "status_code", 500),
code=_code,
provider_specific_fields=getattr(e, "provider_specific_fields", None),
headers=headers,
)

View file

@ -2269,6 +2269,36 @@ class TestHandleLLMApiExceptionDictDetail:
assert proxy_exc.message == "Content blocked by guardrail"
assert proxy_exc.provider_specific_fields is None
async def test_not_found_error_preserves_404(self):
"""NotFoundError with status_code=404 should map to ProxyException code=404."""
from litellm.exceptions import NotFoundError
exc = NotFoundError(
message="Model gemini-3.1-flash-lite-preview not found",
model="gemini-3.1-flash-lite-preview",
llm_provider="gemini",
)
proxy_exc = await self._invoke(exc)
assert proxy_exc.code == "404"
assert "NotFoundError" in proxy_exc.message
async def test_exception_with_status_code_propagates(self):
"""Exception with a statically-set status_code should propagate it."""
from litellm.llms.vertex_ai.common_utils import VertexAIError
exc = VertexAIError(
status_code=429,
message="Rate limit exceeded",
)
proxy_exc = await self._invoke(exc)
assert proxy_exc.code == "429"
async def test_exception_without_status_code_defaults_to_500(self):
"""Exception with no status_code attribute defaults to 500."""
exc = ValueError("Something broke")
proxy_exc = await self._invoke(exc)
assert proxy_exc.code == "500"
class TestAsyncStreamingDataGeneratorFastPath:
"""Fast/slow path branching in async_streaming_data_generator."""