From 40cf96e7806962df26944a15f173fefc324f9ce4 Mon Sep 17 00:00:00 2001 From: vanika02 Date: Fri, 14 Aug 2026 15:15:58 +0000 Subject: [PATCH] fix(responses): validate invalid input types --- litellm/responses/main.py | 12 +++++++ .../test_responses_prompt_management.py | 36 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/litellm/responses/main.py b/litellm/responses/main.py index e0af363b1a5..5b9dc228e7c 100644 --- a/litellm/responses/main.py +++ b/litellm/responses/main.py @@ -465,6 +465,12 @@ async def aresponses( ) and litellm_logging_obj.should_run_prompt_management_hooks(prompt_id=prompt_id, non_default_params=kwargs): if isinstance(input, str): client_input: list[AllMessageValues] = [{"role": "user", "content": input}] + elif not isinstance(input, list): + raise litellm.BadRequestError( + message=f"'input' must be a string or list of input items, got {type(input).__name__}", + model=model, + llm_provider=custom_llm_provider or "unknown", + ) else: client_input = [item for item in input if isinstance(item, dict) and "role" in item] ( @@ -579,6 +585,12 @@ def _apply_prompt_management_to_responses_call( if isinstance(input, str): client_input: list[AllMessageValues] = [{"role": "user", "content": input}] + elif not isinstance(input, list): + raise litellm.BadRequestError( + message=f"'input' must be a string or list of input items, got {type(input).__name__}", + model=model, + llm_provider=custom_llm_provider or "unknown", + ) else: client_input = [item for item in input if isinstance(item, dict) and "role" in item] diff --git a/tests/test_litellm/responses/test_responses_prompt_management.py b/tests/test_litellm/responses/test_responses_prompt_management.py index 7044d8384f8..d76b0f93571 100644 --- a/tests/test_litellm/responses/test_responses_prompt_management.py +++ b/tests/test_litellm/responses/test_responses_prompt_management.py @@ -19,6 +19,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest +import litellm from litellm.integrations.anthropic_cache_control_hook import ( AnthropicCacheControlHook, ) @@ -410,6 +411,23 @@ class TestResponsesAPIPromptManagement: assert handler_call_kwargs.get("custom_llm_provider") == "anthropic" + def test_invalid_input_type_raises_bad_request_error(self): + """Non-string, non-list input should raise BadRequestError.""" + logging_obj = _make_logging_obj( + merged_model="openai/gpt-4o", + merged_messages=[], + ) + + patches = _patch_responses_dispatch() + with patches[0], patches[1], patches[2], patches[3]: + with pytest.raises(litellm.BadRequestError, match="input"): + litellm.responses( + input=12345, + model="gpt-4o", + prompt_id="test-prompt", + litellm_logging_obj=logging_obj, + ) + class TestAsyncResponsesAPIPromptManagement: """Tests for the async aresponses() prompt management path. @@ -539,3 +557,21 @@ class TestAsyncResponsesAPIPromptManagement: assert sent_input[0]["cache_control"] == {"type": "ephemeral"} assert sent_input[1] == reasoning_item assert sent_input[2]["id"] == "msg_1" + + @pytest.mark.asyncio + async def test_async_invalid_input_type_raises_bad_request_error(self): + """Non-string, non-list input should raise BadRequestError.""" + logging_obj = _make_logging_obj( + merged_model="openai/gpt-4o", + merged_messages=[], + ) + logging_obj.async_failure_handler = AsyncMock() + patches = _patch_responses_dispatch() + with patches[0], patches[1], patches[2], patches[3]: + with pytest.raises(litellm.BadRequestError, match="input"): + await litellm.aresponses( + input=12345, + model="gpt-4o", + prompt_id="test-prompt", + litellm_logging_obj=logging_obj, + ) \ No newline at end of file