{"record":{"id":"f7d4bdbbe31e5960","repo":"deepset-ai/haystack","slug":"meta-must-be-a-dictionary","errorCode":null,"errorMessage":"meta must be a dictionary","messagePattern":"meta must be a dictionary","errorType":"exception","errorClass":"TemplateSyntaxError","httpStatus":null,"severity":"error","filePath":"haystack/utils/jinja2_chat_extension.py","lineNumber":207,"sourceCode":"                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(\n            self.call_method(\n                name=\"_build_chat_message_json\",\n                args=[role_expr, name_expr or nodes.Const(None), meta_expr or nodes.Dict([])],\n            ),\n            [],\n            [],\n            body,\n        ).set_lineno(lineno)\n\n    def _build_chat_message_json(self, role: str, name: str | None, meta: dict, caller: Callable[[], str]) -> str:\n        \"\"\"\n        Build a ChatMessage object from template content and serialize it to a JSON string.","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/utils/jinja2_chat_extension.py#L189-L225","documentation":"TemplateSyntaxError raised by `_parse_message_tag` when the optional meta= attribute of a {% message %} tag is not a Jinja2 Dict node. Meta must be written as a dictionary literal in the template so it can be attached to the built ChatMessage.","triggerScenarios":"Writing `{% message role='user' meta='foo' %}` or `meta=meta_dict` (a name/expression instead of a literal dict), so the parsed node is a Const or Name rather than nodes.Dict.","commonSituations":"Trying to pass a context variable as meta instead of a literal; quoting the dict into a string; omitting braces: meta=source instead of meta={'source': 'docs'}.","solutions":["Write meta as an inline dictionary literal: meta={'source': 'wiki', 'page': 1}","Remove the meta attribute if metadata is not required","Set metadata on the resulting ChatMessage in Python code instead of in the template"],"exampleFix":"// before\n{% message role='user' meta=metadata %}Hello{% endmessage %}\n// after\n{% message role='user' meta={'source': 'wiki'} %}Hello{% endmessage %}","handlingStrategy":"validation","validationCode":"import re\nfor m in re.finditer(r\"meta\\s*=\\s*([^\\s%}]+)\", template):\n    assert m.group(1).startswith(\"{\"), f\"meta must be a dict literal, got {m.group(1)}\"","typeGuard":"null","tryCatchPattern":"from jinja2.exceptions import TemplateSyntaxError\ntry:\n    env.parse(template)\nexcept TemplateSyntaxError as e:\n    if \"meta must be a dictionary\" in str(e):\n        raise ValueError(\"Use meta={'key': 'value'} inline in the template\") from e\n    raise","preventionTips":["Write meta as an inline dict literal: meta={'k': 'v'}","Don't pass context variables or strings as meta; set metadata in Python after building the message","Keep meta simple and serializable"],"tags":["haystack","jinja2","template-syntax-error","message-tag","meta-attribute"],"backgroundTag":"invalid-argument-type","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}