From 95b22abd0f767d9ee25965b160317d358957c6d1 Mon Sep 17 00:00:00 2001 From: Ahmet Selim FEDAKAR <122402435+selimfedakar@users.noreply.github.com> Date: Wed, 28 Oct 2026 13:18:16 +0300 Subject: [PATCH] fix: wrap non-JSON decisions responses in DecisionsResponseValidationError transform_decisions_response validated the raw body with validate_json outside the try/except, so a non-JSON upstream body (e.g. an HTML error page) raised an unhandled pydantic ValidationError. Move validate_json inside the try so a malformed body surfaces as DecisionsResponseValidationError, like a schema mismatch in parse_response. Fixes #48660 --- .../llms/base_llm/decisions/transformation.py | 2 +- ...t_transform_decisions_response_non_json.py | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/unit/llms/base_llm/decisions/test_transform_decisions_response_non_json.py diff --git a/litellm/llms/base_llm/decisions/transformation.py b/litellm/llms/base_llm/decisions/transformation.py index b3df4654a6b..e8e4b77e757 100644 --- a/litellm/llms/base_llm/decisions/transformation.py +++ b/litellm/llms/base_llm/decisions/transformation.py @@ -657,8 +657,8 @@ class BaseDecisionsConfig(ABC): raw_response: httpx.Response, request: DecisionsIRRequest, ) -> DecisionsIRResponse: - payload: Final[object] = _PAYLOAD_ADAPTER.validate_json(raw_response.content) try: + payload: Final[object] = _PAYLOAD_ADAPTER.validate_json(raw_response.content) return self.parse_response(payload, request) except ValidationError as error: raise DecisionsResponseValidationError( diff --git a/tests/unit/llms/base_llm/decisions/test_transform_decisions_response_non_json.py b/tests/unit/llms/base_llm/decisions/test_transform_decisions_response_non_json.py new file mode 100644 index 00000000000..e80d15f57d7 --- /dev/null +++ b/tests/unit/llms/base_llm/decisions/test_transform_decisions_response_non_json.py @@ -0,0 +1,26 @@ +from typing import cast + +import httpx +import pytest + +from litellm.llms.base_llm.decisions.transformation import ( + BaseDecisionsConfig, + DecisionsResponseValidationError, +) +from litellm.types.decisions import DecisionsIRRequest + + +def test_transform_decisions_response_wraps_non_json_body(): + """Regression for #48660: a non-JSON response body raised an unhandled + pydantic ValidationError because `validate_json` ran outside the + try/except. It must surface as DecisionsResponseValidationError instead.""" + config = BaseDecisionsConfig() + raw_response = httpx.Response(status_code=502, content=b"Bad Gateway") + + with pytest.raises(DecisionsResponseValidationError): + config.transform_decisions_response( + model="jev-latest", + custom_llm_provider="systemone", + raw_response=raw_response, + request=cast(DecisionsIRRequest, None), + )