langchain-ai/langchain · error · ValueError
Invalid image template: {tmpl}
Error message
Invalid image template: {tmpl} What it means
In the image-template branch of from_messages/from_template, an image entry whose value is neither str nor dict is rejected with ValueError('Invalid image template'). The branch's type analysis marks this code unreachable (# type: ignore[unreachable]) because the outer isinstance(tmpl, tuple) dispatch should constrain the shape, so hitting it means the dispatch contract was violated (e.g. via unusual subclasses or mutated input).
Source
Thrown at libs/core/langchain_core/prompts/chat.py:514
template_format=template_format,
)
elif isinstance(img_template, dict):
img_template = dict(img_template)
for key in ["url", "path", "detail"]:
if key in img_template:
input_variables.extend(
get_template_variables(
img_template[key], template_format
)
)
img_template_obj = ImagePromptTemplate(
input_variables=input_variables,
template=img_template,
template_format=template_format,
)
else:
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)View on GitHub (pinned to e32fa9a52e)
Solutions
- Make every image entry either a format string or a dict with keys among 'url', 'path', 'detail'
- Validate assembled template lists before passing them to from_messages: assert each payload is str or dict
Example fix
# before
("human", [{"type": "image_url", "image_url": image_bytes}]) # ValueError
# after
("human", [{"type": "image_url", "image_url": {"url": build_url(image_bytes)}}]) Defensive patterns
Strategy: type-guard
Validate before calling
def valid_image_entry(entry) -> bool:
t = entry.get("image_url") if isinstance(entry, dict) else entry
return isinstance(t, (str, dict)) Type guard
def is_image_template(t) -> bool:
return isinstance(t, (str, dict)) Prevention
- Validate programmatically assembled message tuples against the (str | dict) image contract before from_messages
When it happens
Trigger: Supplying an image message element whose payload is an int, None, bytes, or an object that str/dict checks fail on, typically through dynamically assembled template lists that bypass static typing.
Common situations: Programmatic prompt builders that splice user/config data into message tuples without validating shape; serialization round-trips that turn a dict into something else.
Related errors
- Only one format variable allowed per image template.\nGot: {
- variable {self.variable_name} should be a list of base messa
- Partial variables are not supported for list of templates.
- jinja2 is unsafe and is not supported for templates expresse
- Invalid template: {tmpl}
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/60b455c50091ae20.
Report an issue: GitHub.