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 attribute

View on GitHub (pinned to e318778c9b)

Solutions

  1. Add a role= attribute as the first attribute of the {% message %} tag
  2. Move name=/meta= attributes after role=
  3. 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

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


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/6cc94066f966d75d. Report an issue: GitHub.