From 40cf96e7806962df26944a15f173fefc324f9ce4 Mon Sep 17 00:00:00 2001 From: vanika02 Date: Fri, 14 Aug 2026 15:15:58 +0000 Subject: [PATCH 1/5] 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 From 2decf0dfe0a1adeca53a103d12abbf9eedba97e0 Mon Sep 17 00:00:00 2001 From: vanika02 Date: Fri, 14 Aug 2026 16:31:43 +0000 Subject: [PATCH 2/5] fix(responses): handle invalid input types --- litellm/responses/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litellm/responses/main.py b/litellm/responses/main.py index 5b9dc228e7c..84c0403ffb2 100644 --- a/litellm/responses/main.py +++ b/litellm/responses/main.py @@ -465,7 +465,7 @@ 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): + elif not isinstance(input, list): # pyright: ignore[reportUnnecessaryIsInstance] raise litellm.BadRequestError( message=f"'input' must be a string or list of input items, got {type(input).__name__}", model=model, @@ -585,7 +585,7 @@ def _apply_prompt_management_to_responses_call( if isinstance(input, str): client_input: list[AllMessageValues] = [{"role": "user", "content": input}] - elif not isinstance(input, list): + elif not isinstance(input, list): # pyright: ignore[reportUnnecessaryIsInstance] raise litellm.BadRequestError( message=f"'input' must be a string or list of input items, got {type(input).__name__}", model=model, From 001662e3eb06f8b5354a31b265bc1a32fa599fc1 Mon Sep 17 00:00:00 2001 From: vanika02 Date: Sat, 15 Aug 2026 04:22:04 +0000 Subject: [PATCH 3/5] style(responses): format input validation --- litellm/responses/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litellm/responses/main.py b/litellm/responses/main.py index 84c0403ffb2..eb4d17d4099 100644 --- a/litellm/responses/main.py +++ b/litellm/responses/main.py @@ -465,7 +465,7 @@ 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): # pyright: ignore[reportUnnecessaryIsInstance] + elif not isinstance(input, list): # pyright: ignore[reportUnnecessaryIsInstance] raise litellm.BadRequestError( message=f"'input' must be a string or list of input items, got {type(input).__name__}", model=model, From 9dad224aa9f397a1829f2405e566ca20379f6bc1 Mon Sep 17 00:00:00 2001 From: vanika02 Date: Sat, 15 Aug 2026 04:36:42 +0000 Subject: [PATCH 4/5] style(responses): format pyright ignore --- litellm/responses/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litellm/responses/main.py b/litellm/responses/main.py index eb4d17d4099..891f845dacd 100644 --- a/litellm/responses/main.py +++ b/litellm/responses/main.py @@ -585,7 +585,7 @@ def _apply_prompt_management_to_responses_call( if isinstance(input, str): client_input: list[AllMessageValues] = [{"role": "user", "content": input}] - elif not isinstance(input, list): # pyright: ignore[reportUnnecessaryIsInstance] + elif not isinstance(input, list): # pyright: ignore[reportUnnecessaryIsInstance] raise litellm.BadRequestError( message=f"'input' must be a string or list of input items, got {type(input).__name__}", model=model, From 9f4934e2a506aeee2ab08e89183b3fc53b533186 Mon Sep 17 00:00:00 2001 From: vanika02 Date: Sat, 15 Aug 2026 04:48:38 +0000 Subject: [PATCH 5/5] style(responses): explain type validation suppressions --- litellm/responses/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litellm/responses/main.py b/litellm/responses/main.py index 891f845dacd..b201f139fea 100644 --- a/litellm/responses/main.py +++ b/litellm/responses/main.py @@ -465,7 +465,7 @@ 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): # pyright: ignore[reportUnnecessaryIsInstance] + elif not isinstance(input, list): # pyright: ignore[reportUnnecessaryIsInstance] # runtime input can come from untrusted client payload raise litellm.BadRequestError( message=f"'input' must be a string or list of input items, got {type(input).__name__}", model=model, @@ -585,7 +585,7 @@ def _apply_prompt_management_to_responses_call( if isinstance(input, str): client_input: list[AllMessageValues] = [{"role": "user", "content": input}] - elif not isinstance(input, list): # pyright: ignore[reportUnnecessaryIsInstance] + elif not isinstance(input, list): # pyright: ignore[reportUnnecessaryIsInstance] # runtime input can come from untrusted client payload raise litellm.BadRequestError( message=f"'input' must be a string or list of input items, got {type(input).__name__}", model=model,