deepset-ai/haystack · error · TemplateSyntaxError

expected token 'assign'

Error message

expected token 'assign'

What it means

After reading the `role` name token, the parser calls expect("assign") requiring an = sign. Jinja2 raises TemplateSyntaxError("expected token 'assign'") when role is not followed by `=`, e.g. when a value or another attribute name appears instead.

Source

Thrown at haystack/utils/jinja2_chat_extension.py:183

        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
        meta_expr = None

View on GitHub (pinned to e318778c9b)

Solutions

  1. Add the missing `=` after role: role="user"
  2. Quote the role value as a Python/Jinja string literal
  3. Validate the whole tag: {% message role="user" %}...{% endmessage %}

Example fix

// before
{% message role "user" %}Hi{% endmessage %}
// after
{% message role="user" %}Hi{% endmessage %}
Defensive patterns

Strategy: validation

Validate before calling

import re
MSG_ROLE = re.compile(r"{%\s*message\s+role\s*=\s*['\"]\w+['\"]")
assert MSG_ROLE.search(template), "message tag needs role=\"...\""

Try / catch

try:
    env.from_string(template)
except TemplateSyntaxError as e:
    print(f"line {e.lineno}: {e.message}")

Prevention

When it happens

Trigger: Writing {% message role "user" %} (missing =), or {% message role user %}, or a space/typo such as role-"user" in a ChatPromptBuilder template.

Common situations: Template syntax confusion from other templating engines; hand-editing templates and dropping the `=`.

Related errors


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