deepset-ai/haystack · error · TemplateSyntaxError

name must be a string

Error message

name must be a string

What it means

TemplateSyntaxError raised by `_parse_message_tag` when the optional name= attribute of a {% message %} tag parses to a non-string constant. The name is passed through to ChatMessage.name and must be a string literal in the template.

Source

Thrown at haystack/utils/jinja2_chat_extension.py:198

        # 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
        if parser.stream.current.test("name:meta"):
            parser.stream.skip()
            parser.stream.expect("assign")
            meta_expr = parser.parse_expression()
            if not isinstance(meta_expr, nodes.Dict):
                raise TemplateSyntaxError("meta must be a dictionary", lineno)

        # Parse message body
        body = parser.parse_statements(("name:endmessage",), drop_needle=True)

        # Build message node with all parameters
        return nodes.CallBlock(
            self.call_method(
                name="_build_chat_message_json",
                args=[role_expr, name_expr or nodes.Const(None), meta_expr or nodes.Dict([])],

View on GitHub (pinned to e318778c9b)

Solutions

  1. Quote the name: name='my-name' so it parses as a string constant
  2. Remove the name attribute if it is not needed
  3. Verify the expression is a literal string, not a variable or number

Example fix

// before
{% message role='assistant' name=claude %}...{% endmessage %}
// after
{% message role='assistant' name='claude' %}...{% endmessage %}
Defensive patterns

Strategy: validation

Validate before calling

import re
for m in re.finditer(r"name\s*=\s*([^\s%}]+)", template):
    assert m.group(1).startswith("'" ) or m.group(1).startswith('"'), f"name must be a quoted string, got {m.group(1)}"

Type guard

null

Try / catch

from jinja2.exceptions import TemplateSyntaxError
try:
    env.parse(template)
except TemplateSyntaxError as e:
    if "name must be a string" in str(e):
        raise ValueError("Quote the name attribute: name='my-name'") from e
    raise

Prevention

When it happens

Trigger: Writing `{% message role='assistant' name=42 %}` or `name=some_list`, i.e. any expression whose constant value is not a str (numbers, booleans, lists).

Common situations: Forgetting quotes around the name: name=claude instead of name='claude'; passing a numeric identifier; YAML/JSON-influenced habits where names are unquoted keys.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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