langchain-ai/langchain · error · ValueError
Invalid template: {tmpl}
Error message
Invalid template: {tmpl} What it means
Inside the sequence-template loop of from_messages/from_template, an element that is neither str, dict, nor an accepted shape falls through to ValueError('Invalid template: {tmpl}'). Static analysis marks it unreachable because the loop's isinstance chain covers str and dict; reaching it requires an element type outside those branches (int, None, arbitrary objects) slipping into the template list.
Source
Thrown at libs/core/langchain_core/prompts/chat.py:531
msg = f"Invalid image template: {tmpl}" # type: ignore[unreachable]
raise ValueError(msg)
prompt.append(img_template_obj)
elif isinstance(tmpl, dict):
if template_format == "jinja2":
msg = (
"jinja2 is unsafe and is not supported for templates "
"expressed as dicts. Please use 'f-string' or 'mustache' "
"format."
)
raise ValueError(msg)
data_template_obj = DictPromptTemplate(
template=cast("dict[str, Any]", tmpl),
template_format=template_format,
)
prompt.append(data_template_obj)
else:
msg = f"Invalid template: {tmpl}" # type: ignore[unreachable]
raise ValueError(msg)
return cls(prompt=prompt, **kwargs)
msg = f"Invalid template: {template}" # type: ignore[unreachable]
raise ValueError(msg)
@classmethod
def from_template_file(
cls: type[Self],
template_file: str | Path,
input_variables: list[str],
**kwargs: Any,
) -> Self:
"""Create a class from a template file.
Args:
template_file: path to a template file.
input_variables: list of input variables.
**kwargs: Keyword arguments to pass to the constructor.
View on GitHub (pinned to e32fa9a52e)
Solutions
- Filter the list before passing: [t for t in templates if t is not None]
- Ensure every element is a str or dict as documented for list templates
Example fix
# before parts = [system_prompt, user_section or None] ChatPromptTemplate.from_messages(parts) # ValueError on None # after parts = [p for p in [system_prompt, user_section] if p is not None] ChatPromptTemplate.from_messages(parts)
Defensive patterns
Strategy: validation
Validate before calling
def clean_template_list(templates):
bad = [t for t in templates if not isinstance(t, (str, dict))]
if bad:
msg = f"non-str/dict template elements: {bad!r}"
raise ValueError(msg)
return templates Type guard
def is_valid_template_element(t) -> bool:
return isinstance(t, (str, dict)) Prevention
- Filter None out of conditionally assembled template lists before from_messages
- Keep template lists homogeneous (str/dict) when loading from config files
When it happens
Trigger: Passing a list-of-templates element like 42, None, or a custom object: ChatPromptTemplate.from_messages(['system: hi', None]) — the None is neither str nor dict and trips the fallthrough.
Common situations: Optional message sections concatenated with 'or []' patterns that actually yield [None]; data-driven prompt assembly from JSON configs where a field is null; conditional splices inserting a sentinel value.
Related errors
- variable {self.variable_name} should be a list of base messa
- Invalid template: {template}
- Got mismatched input_variables. Expected: {input_vars}. Got:
- Unexpected input: {message_template}
- INVALID_PROMPT_INPUT
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/2e8b277a36628fb1.
Report an issue: GitHub.