mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-21 00:21:49 +00:00
fix(exceptions): keep internal_server_error as the public type of an upstream 500
PR #40243 started carrying the upstream error body on InternalServerError so the Responses response.failed event can report the provider's code and message, and openai's APIError.__init__ took the body's type along with it. The proxy then answered an OpenAI-compatible upstream 500 with type server_error while a 502 and a 503 kept internal_server_error, and the integration contract in test_observed_routing.py went red. Pin the type the way RateLimitError pins throttling_error, keeping the body.
This commit is contained in:
parent
faed57f92c
commit
ddac683ec6
3 changed files with 23 additions and 2 deletions
|
|
@ -787,6 +787,7 @@ class InternalServerError(openai.InternalServerError):
|
|||
super().__init__(
|
||||
self.message, response=self.response, body=body
|
||||
) # Call the base class constructor with the parameters it needs
|
||||
self.type = "internal_server_error"
|
||||
|
||||
def __str__(self):
|
||||
_message = self.message
|
||||
|
|
|
|||
|
|
@ -1438,9 +1438,12 @@ def test_openai_compatible_vendor_400_keeps_body_but_not_headers():
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("status_code", "mapped_class"), [(429, litellm.RateLimitError), (500, litellm.InternalServerError)]
|
||||
("status_code", "mapped_class", "reported_type"),
|
||||
[(429, litellm.RateLimitError, "throttling_error"), (500, litellm.InternalServerError, "internal_server_error")],
|
||||
)
|
||||
def test_openai_429_and_500_keep_body(status_code: int, mapped_class: type[openai.APIError]):
|
||||
def test_openai_429_and_500_keep_body_but_report_litellm_type(
|
||||
status_code: int, mapped_class: type[openai.APIError], reported_type: str
|
||||
):
|
||||
with pytest.raises(mapped_class) as exc_info:
|
||||
exception_type(
|
||||
model="gpt-5.4-mini",
|
||||
|
|
@ -1458,6 +1461,7 @@ def test_openai_429_and_500_keep_body(status_code: int, mapped_class: type[opena
|
|||
"code": str(status_code),
|
||||
"message": "upstream cannot complete this response",
|
||||
}
|
||||
assert exc_info.value.type == reported_type
|
||||
|
||||
|
||||
def test_litellm_proxy_repeated_response_header_keeps_each_value():
|
||||
|
|
|
|||
|
|
@ -147,6 +147,22 @@ def test_a_status_carried_by_an_exception_drives_the_type_it_reports():
|
|||
assert openai_error_type(exc, error_status_code(exc, 400)) == "permission_error"
|
||||
|
||||
|
||||
def test_an_upstream_5xx_body_does_not_relabel_the_internal_server_error():
|
||||
"""The upstream body rides along on the exception for the Responses ``response.failed``
|
||||
event, but a 500 keeps answering the proxy's own ``internal_server_error`` label."""
|
||||
from litellm.exceptions import InternalServerError
|
||||
|
||||
carried = InternalServerError(
|
||||
message="Controlled provider failure",
|
||||
model="gpt-5.4-mini",
|
||||
llm_provider="openai",
|
||||
body={"message": "Controlled provider failure", "type": "server_error", "code": "500"},
|
||||
)
|
||||
|
||||
assert carried.body == {"message": "Controlled provider failure", "type": "server_error", "code": "500"}
|
||||
assert openai_error_type(carried, error_status_code(carried, 400)) == "internal_server_error"
|
||||
|
||||
|
||||
def test_a_stringified_none_type_or_param_is_treated_as_absent():
|
||||
from litellm.exceptions import BadRequestError
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue