BerriAI/litellm · error · ValueError
messages is required
Error message
messages is required
What it means
validate_input_kwargs raises when 'messages' is missing from kwargs or is not a list. The bridge converts chat messages into Responses API input items, so a valid list of message dicts is mandatory. This is an internal-API contract check; normal litellm.completion calls always supply messages.
Source
Thrown at litellm/completion_extras/litellm_responses_transformation/handler.py:118
return response
def validate_input_kwargs(self, kwargs: dict) -> ResponsesToCompletionBridgeHandlerInputKwargs:
from litellm import LiteLLMLoggingObj
from litellm.types.utils import ModelResponse
typed_kwargs: Final[dict[str, object]] = kwargs
model: Final = typed_kwargs.get("model")
if model is None or not isinstance(model, str):
raise ValueError("model is required")
custom_llm_provider: Final = typed_kwargs.get("custom_llm_provider")
if custom_llm_provider is None or not isinstance(custom_llm_provider, str):
raise ValueError("custom_llm_provider is required")
messages: Final = typed_kwargs.get("messages")
if messages is None or not isinstance(messages, list):
raise ValueError("messages is required")
optional_params: Final = typed_kwargs.get("optional_params")
if optional_params is None or not isinstance(optional_params, dict):
raise ValueError("optional_params is required")
litellm_params: Final = typed_kwargs.get("litellm_params")
if litellm_params is None or not isinstance(litellm_params, dict):
raise ValueError("litellm_params is required")
headers: Final = typed_kwargs.get("headers")
if headers is None or not isinstance(headers, dict):
raise ValueError("headers is required")
model_response: Final = typed_kwargs.get("model_response")
if model_response is None or not isinstance(model_response, ModelResponse):
raise ValueError("model_response is required")
logging_obj: Final = typed_kwargs.get("logging_obj")View on GitHub (pinned to 6c2dcb801b)
Solutions
- Pass messages as a list of role/content dicts: [{"role": "user", "content": "..."}]
- Prefer litellm.completion(model=..., messages=[...]) which validates and forwards everything
- Check upstream code that builds kwargs for a mutation that drops or replaces the messages key
Example fix
# before
kwargs = {"model": "gpt-4o", "messages": "hello"}
# after
kwargs = {"model": "gpt-4o", "messages": [{"role": "user", "content": "hello"}]} Defensive patterns
Strategy: validation
Validate before calling
def has_messages_kwarg(kwargs: dict) -> bool:
return isinstance(kwargs.get("messages"), list) and len(kwargs["messages"]) > 0 Type guard
def is_message_list(v) -> bool:
return isinstance(v, list) and all(
isinstance(m, dict) and isinstance(m.get("role"), str) for m in v
) Prevention
- Always pass messages as a list of {role, content} dicts
- Validate message shape at your API boundary before calling litellm
When it happens
Trigger: Calling the bridge handler with kwargs where messages is None, a string, a single dict, or absent.
Common situations: Direct handler use in custom pipelines; passing a bare prompt string where a messages list is expected; tests with incomplete fixture data.
Related errors
- model is required
- custom_llm_provider is required
- optional_params is required
- litellm_params is required
- headers is required
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/94b47104eb3dcd64.
Report an issue: GitHub.