diff --git a/litellm/llms/gemini/interactions/transformation.py b/litellm/llms/gemini/interactions/transformation.py index ab2c1440fb7..0e898147d90 100644 --- a/litellm/llms/gemini/interactions/transformation.py +++ b/litellm/llms/gemini/interactions/transformation.py @@ -313,6 +313,12 @@ class GoogleAIStudioInteractionsConfig(BaseInteractionsAPIConfig): raw_response: httpx.Response, logging_obj: LiteLLMLoggingObj, ) -> InteractionsAPIResponse: + if not 200 <= raw_response.status_code < 300: + raise GeminiError( + message=raw_response.text, + status_code=raw_response.status_code, + headers=dict(raw_response.headers), + ) try: raw_json: Final = _interaction_body(raw_response) except Exception: diff --git a/tests/unit/interactions/test_gemini_interactions_transformation.py b/tests/unit/interactions/test_gemini_interactions_transformation.py index 2809c12ae47..5e394e9f218 100644 --- a/tests/unit/interactions/test_gemini_interactions_transformation.py +++ b/tests/unit/interactions/test_gemini_interactions_transformation.py @@ -10,12 +10,13 @@ Covers: from unittest.mock import MagicMock, patch +import httpx import pytest - from litellm.interactions.litellm_responses_transformation.streaming_iterator import ( LiteLLMResponsesInteractionsStreamingIterator, ) +from litellm.llms.gemini.common_utils import GeminiError from litellm.llms.gemini.interactions.transformation import ( GoogleAIStudioInteractionsConfig, ) @@ -464,6 +465,32 @@ class TestInteractionOperationUrls: ) +class TestGetInteractionResponse: + @pytest.mark.parametrize("status_code", [404, 500]) + def test_non_2xx_raises_even_when_the_error_body_is_json( + self, config: GoogleAIStudioInteractionsConfig, status_code: int + ) -> None: + raw_response = httpx.Response( + status_code, + json={"error": {"code": status_code, "message": "boom", "status": "INTERNAL"}}, + request=httpx.Request("GET", "https://generativelanguage.googleapis.com/v1beta/interactions/x"), + ) + with pytest.raises(GeminiError) as raised: + config.transform_get_interaction_response(raw_response=raw_response, logging_obj=MagicMock()) + assert raised.value.status_code == status_code + assert "boom" in str(raised.value) + + def test_2xx_parses_the_interaction(self, config: GoogleAIStudioInteractionsConfig) -> None: + raw_response = httpx.Response( + 200, + json={"id": "interaction-1", "object": "interaction", "status": "completed", "steps": []}, + request=httpx.Request("GET", "https://generativelanguage.googleapis.com/v1beta/interactions/x"), + ) + response = config.transform_get_interaction_response(raw_response=raw_response, logging_obj=MagicMock()) + assert response.id == "interaction-1" + assert response.status == "completed" + + class TestTransformRequestSchemaCoalescing: """Test new-schema request coalescing (Api-Revision: 2026-05-20)."""