{"record":{"id":"054445ec767dd1c2","repo":"deepset-ai/haystack","slug":"expected-token-assign-got","errorCode":null,"errorMessage":"expected token 'assign', got ...","messagePattern":"expected token 'assign', got \\.\\.\\.","errorType":"panic","errorClass":"TemplateSyntaxError","httpStatus":null,"severity":"error","filePath":"haystack/utils/jinja2_chat_extension.py","lineNumber":195,"sourceCode":"        :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\n        meta_expr = None\n        if parser.stream.current.test(\"name:meta\"):\n            parser.stream.skip()\n            parser.stream.expect(\"assign\")\n            meta_expr = parser.parse_expression()\n            if not isinstance(meta_expr, nodes.Dict):\n                raise TemplateSyntaxError(\"meta must be a dictionary\", lineno)\n\n        # Parse message body\n        body = parser.parse_statements((\"name:endmessage\",), drop_needle=True)\n\n        # Build message node with all parameters\n        return nodes.CallBlock(","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/utils/jinja2_chat_extension.py#L177-L213","documentation":"The message tag's optional name= attribute is parsed only if the token `name` is present, and after `name` the parser expects an `=` (assign). Jinja2 raises TemplateSyntaxError(\"expected token 'assign', got ...\") when `name` is not immediately followed by `=`. The got ... part shows the offending token.","triggerScenarios":"Writing {% message role=\"user\" name \"foo\" %} or {% message role=\"user\" name= %} (missing value) in a ChatPromptBuilder template.","commonSituations":"Typos while hand-writing templates; confusing positional arguments with keyword-style attributes.","solutions":["Write name as a keyword attribute: name=\"greeting\"","Ensure a valid expression follows the `=` (a quoted string, since name must be a string)","Remove the stray token between `name` and `=`"],"exampleFix":"// before\n{% message role=\"user\" name \"greeting\" %}Hi{% endmessage %}\n// after\n{% message role=\"user\" name=\"greeting\" %}Hi{% endmessage %}","handlingStrategy":"validation","validationCode":"import re\nassert re.search(r\"\\bname\\s*=\\s*['\\\"][^'\\\"]+['\\\"]\", tag_src), \"name must be name=\\\"...\\\"\"","typeGuard":null,"tryCatchPattern":"try:\n    env.from_string(template)\nexcept TemplateSyntaxError as e:\n    print(f\"line {e.lineno}: {e.message}\")","preventionTips":["Write optional attributes strictly as key=value pairs","Ensure name values are quoted strings (they must be str)","Test-render all prompt templates in CI"],"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"}