BerriAI/litellm · error · ValueError
Bad Request: messages is required for Anthropic Messages Req
Error message
Bad Request: messages is required for Anthropic Messages Request
What it means
Same adapter validation path as the 'model' check, but for the second required field: 'messages'. The Anthropic Messages API mandates a non-empty messages array, and this handler enforces it client-side by popping 'messages' from kwargs and rejecting falsy values before constructing the typed request.
Source
Thrown at litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py:171
Translate Anthropic request params to OpenAI format, returning tool name mapping.
This method handles truncation of tool names that exceed OpenAI's 64-character
limit. The mapping allows restoring original names when translating responses.
Returns:
Tuple of (openai_request, tool_name_mapping)
- tool_name_mapping maps truncated tool names back to original names
"""
#########################################################
# Validate required params
#########################################################
model: Final = kwargs.pop("model")
messages: Final = kwargs.pop("messages")
if not model:
raise ValueError("Bad Request: model is required for Anthropic Messages Request")
if not messages:
raise ValueError("Bad Request: messages is required for Anthropic Messages Request")
#########################################################
# Created Typed Request Body
#########################################################
request_body: Final = AnthropicMessagesRequest(model=model, messages=messages, **kwargs)
(
translated_body,
tool_name_mapping,
) = LiteLLMAnthropicMessagesAdapter().translate_anthropic_to_openai(anthropic_message_request=request_body)
return translated_body, tool_name_mapping
def translate_completion_output_params(
self,
response: ModelResponse,
tool_name_mapping: dict[str, str] | None = None,
polyfill_result: PolyfillResult | None = None,View on GitHub (pinned to 6c2dcb801b)
Solutions
- Include a non-empty 'messages' array, e.g. [{"role": "user", "content": "hello"}], in the request body.
- If the caller only has a prompt string, wrap it: messages=[{"role": "user", "content": prompt}].
- Guard upstream: reject requests with empty messages before they reach the adapter.
Example fix
# before
kwargs = {"model": "claude-sonnet-4-5", "max_tokens": 100}
handler(**kwargs) # ValueError: messages is required
# after
kwargs = {
"model": "claude-sonnet-4-5",
"max_tokens": 100,
"messages": [{"role": "user", "content": "hello"}],
}
handler(**kwargs) Defensive patterns
Strategy: validation
Validate before calling
def validate_messages(body: dict) -> None:
msgs = body.get("messages")
if not isinstance(msgs, list) or len(msgs) == 0:
raise ValueError("request body must include a non-empty 'messages' array") Type guard
def has_valid_messages(body: dict) -> bool:
msgs = body.get("messages")
return isinstance(msgs, list) and len(msgs) > 0 and all(
isinstance(m, dict) and "role" in m and "content" in m for m in msgs
) Try / catch
try:
handler(**body)
except ValueError as e:
if "messages is required" in str(e):
return http_error(400, "messages is required")
raise Prevention
- Reject empty message arrays in middleware before they reach the adapter.
- When wrapping a bare prompt, always convert it to a messages list of length >= 1.
- Add contract tests asserting every request template contains messages.
When it happens
Trigger: Calling the adapter handler with kwargs missing 'messages', messages=None, or messages=[] (empty list is falsy and also rejected). Common when a caller strips messages for logging/middleware or builds the body from a template that omits them.
Common situations: Proxy middleware that deserializes and re-serializes bodies and drops 'messages' on empty payloads; agent frameworks that call the completion path with only a prompt string instead of messages; empty-list edge cases in tests.
Related errors
- Bad Request: model is required for Anthropic Messages Reques
- WebSearchInterception: missing follow-up messages
- Invalid first message. Should always start with 'role'='user
- Unable to parse anthropic tool result for message: {message}
- Unable to parse anthropic file message: {message}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/2ae11330f45b4f6c.
Report an issue: GitHub.