deepset-ai/haystack · error · TemplateSyntaxError
expected token 'name:role'
Error message
expected token 'name:role'
What it means
This error comes from parser.stream.expect("name:role") inside the {% message %} tag parser: Jinja2 raises TemplateSyntaxError('expected token \'name:role\'', ...) when the first attribute of the message tag is not the literal name `role`. The message tag requires role to be its first attribute.
Source
Thrown at haystack/utils/jinja2_chat_extension.py:182
# Bodyless tag: empty body, no matching end tag required.
return nodes.CallBlock(
self.call_method(name="_build_inserted_messages_json", args=[expr]), [], [], []
).set_lineno(lineno)
def _parse_message_tag(self, parser: Any, lineno: int) -> nodes.Node | list[nodes.Node]:
"""
Parse the message tag and its attributes in the Jinja2 template.
This method handles the parsing of role (mandatory), name (optional), meta (optional) and message body content.
:param parser: The Jinja2 parser instance
:param lineno: The line number of the tag, used for error reporting.
:return: A CallBlock node containing the parsed message configuration
:raises TemplateSyntaxError: If an invalid role is provided
"""
# Parse role attribute (mandatory)
parser.stream.expect("name:role")
parser.stream.expect("assign")
role_expr = parser.parse_expression()
if isinstance(role_expr, nodes.Const):
role = role_expr.value
if role not in self.SUPPORTED_ROLES:
raise TemplateSyntaxError(f"Role must be one of: {', '.join(self.SUPPORTED_ROLES)}", lineno)
# Parse optional name attribute
name_expr = None
if parser.stream.current.test("name:name"):
parser.stream.skip()
parser.stream.expect("assign")
name_expr = parser.parse_expression()
if not isinstance(name_expr.value, str):
raise TemplateSyntaxError("name must be a string", lineno)
# Parse optional meta attributeView on GitHub (pinned to e318778c9b)
Solutions
- Add a role= attribute as the first attribute of the {% message %} tag
- Move name=/meta= attributes after role=
- Ensure correct tag syntax: {% message role="user" %}...{% endmessage %}
Example fix
// before
{% message name="x" %}Hi{% endmessage %}
// after
{% message role="user" name="x" %}Hi{% endmessage %} Defensive patterns
Strategy: validation
Validate before calling
def message_tag_ok(tag_src):
return tag_src.lstrip("{% ").startswith("message role=") Try / catch
try:
Jinja2ChatExtension.parse(env, parser, stream)
except TemplateSyntaxError as e:
print(f"line {e.lineno}: first message attribute must be role=", e.message) Prevention
- Always make role= the first attribute of {% message %}
- Keep a canonical template snippet to copy from
- Compile templates in tests before serving them
When it happens
Trigger: Writing {% message %} without a role attribute, or putting another attribute (name=, meta=) before role=, e.g. {% message name="greet" %}.
Common situations: Hand-writing ChatPromptBuilder templates and omitting or mis-ordering the mandatory role attribute; converting plain Jinja templates to message tags.
Related errors
- expected token 'assign'
- expected token 'assign', got ...
- Invalid Jinja template '{template}': {e}
- Document with ID '{doc.id}' comes from the PDF file '{resolv
- No `jq_schema` nor `content_key` specified. Set either or bo
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/6cc94066f966d75d.
Report an issue: GitHub.