langchain-ai/langchain · error · ValueError
variable {self.variable_name} should be a list of base messa
Error message
variable {self.variable_name} should be a list of base messages, got {value} of type {type(value)} What it means
MessagesPlaceholder._format_messages requires the value bound to its variable to be a Python list (it may be empty, and may be omitted entirely when optional=True). Any other type — a single BaseMessage, a tuple, a generator, None for a non-optional placeholder — raises ValueError telling you it wants 'a list of base messages'.
Source
Thrown at libs/core/langchain_core/prompts/chat.py:186
**kwargs: Keyword arguments to use for formatting.
Returns:
List of `BaseMessage` objects.
Raises:
ValueError: If variable is not a list of messages.
"""
value = (
kwargs.get(self.variable_name, [])
if self.optional
else kwargs[self.variable_name]
)
if not isinstance(value, list):
msg = (
f"variable {self.variable_name} should be a list of base messages, "
f"got {value} of type {type(value)}"
)
raise ValueError(msg) # noqa: TRY004
value = convert_to_messages(value)
if self.n_messages:
value = value[-self.n_messages :]
return value
@property
def input_variables(self) -> list[str]:
"""Input variables for this prompt template.
Returns:
List of input variable names.
"""
return [self.variable_name] if not self.optional else []
@override
def pretty_repr(self, html: bool = False) -> str:
"""Human-readable representation.
View on GitHub (pinned to e32fa9a52e)
Solutions
- Always pass a list: {'history': [m1, m2]} or list(history_tuple)
- If the value can be absent, declare MessagesPlaceholder('history', optional=True) so kwargs default to []
- Convert a single message by wrapping it: {'history': [single_msg]}
Example fix
# before
prompt = ChatPromptTemplate.from_messages([
MessagesPlaceholder("history"), "human: {q}",
])
prompt.invoke({"history": SystemMessage("be terse"), "q": "hi"}) # ValueError
# after
prompt.invoke({"history": [SystemMessage("be terse")], "q": "hi"}) Defensive patterns
Strategy: type-guard
Validate before calling
from langchain_core.messages import BaseMessage
def coerce_history(value):
if isinstance(value, BaseMessage):
return [value]
if not isinstance(value, list):
msg = f"history must be a list of messages, got {type(value)}"
raise ValueError(msg)
return list(value) Type guard
def is_message_list(value) -> bool:
return isinstance(value, list) and all(isinstance(m, BaseMessage) for m in value) Prevention
- Declare MessagesPlaceholder('history', optional=True) whenever history may be absent
- Always wrap single messages in a list at the call site
When it happens
Trigger: Invoking a ChatPromptTemplate containing MessagesPlaceholder('history') with history=SystemMessage(...), history=(msg1, msg2), or history=msg_generator; passing None when the placeholder is not marked optional=True.
Common situations: Conversation-history wiring: retrieving a single last message instead of a list; passing a tuple from a DB row; forgetting to set optional_messages=True for branches where history may be absent.
Related errors
- Unexpected input: {message_template}
- Invalid template: {tmpl}
- Invalid template: {template}
- Got mismatched input_variables. Expected: {input_vars}. Got:
- INVALID_PROMPT_INPUT
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/b05ed659eb8fef5d.
Report an issue: GitHub.