{"record":{"id":"6cc94066f966d75d","repo":"deepset-ai/haystack","slug":"expected-token-name-role","errorCode":null,"errorMessage":"expected token 'name:role'","messagePattern":"expected token 'name:role'","errorType":"panic","errorClass":"TemplateSyntaxError","httpStatus":null,"severity":"error","filePath":"haystack/utils/jinja2_chat_extension.py","lineNumber":182,"sourceCode":"        # Bodyless tag: empty body, no matching end tag required.\n        return nodes.CallBlock(\n            self.call_method(name=\"_build_inserted_messages_json\", args=[expr]), [], [], []\n        ).set_lineno(lineno)\n\n    def _parse_message_tag(self, parser: Any, lineno: int) -> nodes.Node | list[nodes.Node]:\n        \"\"\"\n        Parse the message tag and its attributes in the Jinja2 template.\n\n        This method handles the parsing of role (mandatory), name (optional), meta (optional) and message body content.\n\n        :param parser: The Jinja2 parser instance\n        :param lineno: The line number of the tag, used for error reporting.\n        :return: A CallBlock node containing the parsed message configuration\n        :raises TemplateSyntaxError: If an invalid role is provided\n        \"\"\"\n\n        # Parse role attribute (mandatory)\n        parser.stream.expect(\"name:role\")\n        parser.stream.expect(\"assign\")\n        role_expr = parser.parse_expression()\n\n        if isinstance(role_expr, nodes.Const):\n            role = role_expr.value\n            if role not in self.SUPPORTED_ROLES:\n                raise TemplateSyntaxError(f\"Role must be one of: {', '.join(self.SUPPORTED_ROLES)}\", lineno)\n\n        # Parse optional name attribute\n        name_expr = None\n        if parser.stream.current.test(\"name:name\"):\n            parser.stream.skip()\n            parser.stream.expect(\"assign\")\n            name_expr = parser.parse_expression()\n            if not isinstance(name_expr.value, str):\n                raise TemplateSyntaxError(\"name must be a string\", lineno)\n\n        # Parse optional meta attribute","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/utils/jinja2_chat_extension.py#L164-L200","documentation":"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.","triggerScenarios":"Writing {% message %} without a role attribute, or putting another attribute (name=, meta=) before role=, e.g. {% message name=\"greet\" %}.","commonSituations":"Hand-writing ChatPromptBuilder templates and omitting or mis-ordering the mandatory role attribute; converting plain Jinja templates to message tags.","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 %}"],"exampleFix":"// before\n{% message name=\"x\" %}Hi{% endmessage %}\n// after\n{% message role=\"user\" name=\"x\" %}Hi{% endmessage %}","handlingStrategy":"validation","validationCode":"def message_tag_ok(tag_src):\n    return tag_src.lstrip(\"{% \").startswith(\"message role=\")","typeGuard":null,"tryCatchPattern":"try:\n    Jinja2ChatExtension.parse(env, parser, stream)\nexcept TemplateSyntaxError as e:\n    print(f\"line {e.lineno}: first message attribute must be role=\", e.message)","preventionTips":["Always make role= the first attribute of {% message %}","Keep a canonical template snippet to copy from","Compile templates in tests before serving them"],"tags":["python","jinja2","template-syntax","haystack"],"backgroundTag":"template-syntax-error","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}