BerriAI/litellm · error · ValueError
messages must be a list
Error message
messages must be a list
What it means
Type check inside Converse-format validation: 'messages' must be a Python list. Passing a single message dict, a string, or any other type raises ValueError with this message.
Source
Thrown at litellm/llms/bedrock/count_tokens/transformation.py:267
Args:
request_data: The request payload
Raises:
ValueError: If the request is invalid
"""
if not request_data.get("model"):
raise ValueError("model parameter is required")
input_type: Final = self._detect_input_type(request_data)
if input_type == "converse":
# Validate Converse format (messages-based)
messages: Final = request_data.get("messages", [])
if not messages:
raise ValueError("messages parameter is required for Converse input")
if not isinstance(messages, list):
raise ValueError("messages must be a list")
for i, message in enumerate(messages):
if not isinstance(message, dict):
raise ValueError(f"Message {i} must be a dictionary")
if "role" not in message:
raise ValueError(f"Message {i} must have a 'role' field")
if "content" not in message:
raise ValueError(f"Message {i} must have a 'content' field")
else:
# For InvokeModel format, we need at least some content to count tokens
# The content structure varies by model, so we do minimal validation
if len(request_data) <= 1: # Only has 'model' field
raise ValueError("Request must contain content to count tokens")
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Wrap a single message in a list: messages=[msg] not messages=msg
- Add an assertion before the call: assert isinstance(req['messages'], list)
Example fix
# before
req = {'model': model, 'messages': {'role': 'user', 'content': [...]}}
# after
req = {'model': model, 'messages': [{'role': 'user', 'content': [...]}]} Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(req.get("messages"), list):
raise TypeError("messages must be a list of message dicts") Type guard
def is_message_list(v) -> bool:
return isinstance(v, list) and all(isinstance(m, dict) for m in v) Prevention
- Type payloads with TypedDict/Pydantic models so shape errors surface at parse time
- Wrap single-message convenience APIs at your boundary: msg if list else [msg]
When it happens
Trigger: Calling count tokens with messages being a single message object ({'role':...}) instead of a list of messages, or with a JSON-decoded payload where messages was serialized as something else.
Common situations: SDK wrappers that accept one message for convenience, or deserialization bugs that wrap/unwrap the array incorrectly.
Related errors
- Message {i} must be a dictionary
- model parameter is required
- messages parameter is required for Converse input
- Message {i} must have a 'role' field
- Message {i} must have a 'content' field
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/ed895d2b1800d680.
Report an issue: GitHub.