{"record":{"id":"eca3abb517526680","repo":"aosabook/500lines","slug":"s-r-eca3ab","errorCode":null,"errorMessage":"%s: %r","messagePattern":"%s: %r","errorType":"exception","errorClass":"TempliteSyntaxError","httpStatus":null,"severity":"error","filePath":"template-engine/template-engine.markdown","lineNumber":1208,"sourceCode":"```python\n        else:\n            self._variable(expr, self.all_vars)\n            code = \"c_%s\" % expr\n        return code\n```\n<!-- [[[end]]] -->\n\n\n#### Helper Functions\n\nDuring compilation, we used a few helper functions.  The `_syntax_error` method\nsimply puts together a nice error message and raises the exception:\n\n<!-- [[[cog include(\"templite.py\", first=\"def _syntax_error\", numblanks=1, dedent=False) ]]] -->\n```python\n    def _syntax_error(self, msg, thing):\n        \"\"\"Raise a syntax error using `msg`, and showing `thing`.\"\"\"\n        raise TempliteSyntaxError(\"%s: %r\" % (msg, thing))\n```\n<!-- [[[end]]] -->\n\nThe `_variable` method helps us with validating variable names and adding them\nto the sets of names we collected during compilation.  We use a\nregex to check that the name is a valid Python identifier, then add the name to\nthe set:\n\n<!-- [[[cog include(\"templite.py\", first=\"def _variable\", numblanks=4, dedent=False) ]]] -->\n```python\n    def _variable(self, name, vars_set):\n        \"\"\"Track that `name` is used as a variable.\n\n        Adds the name to `vars_set`, a set of variable names.\n\n        Raises an syntax error if `name` is not a valid name.\n\n        \"\"\"","sourceCodeStart":1190,"sourceCodeEnd":1226,"githubUrl":"https://github.com/aosabook/500lines/blob/fba689d101eb5600f5c8f4d7fd79912498e950e2/template-engine/template-engine.markdown#L1190-L1226","documentation":"Raised by Code._syntax_error in the Templite template engine (template-engine chapter). During compilation, when the compiler detects malformed template syntax it calls _syntax_error(msg, thing), which raises TempliteSyntaxError formatted as '%s: %r' % (msg, thing) — a human message plus a repr of the offending token/node. It surfaces only at compile time, before any template is rendered.","triggerScenarios":"Compiling a template string with malformed syntax: an unclosed {% %} or {{ }} block, a {% %} tag in an expression context, a malformed {% if %}/{% for %} construct, an unrecognised tag keyword, or an invalid variable name rejected by _variable.","commonSituations":"Hand-editing a template and leaving a dangling delimiter; copy-pasting a fragment that opens a block but never closes it; using Jinja2 syntax ({% endif %} vs this engine's {% end %}) by mistake; a variable name containing characters the identifier regex rejects.","solutions":["Read the %s message and the %r token in the exception to locate the offending construct.","Balance every {% %} block with its matching {% end %} and verify {{ }} braces close.","Use only the tags the engine supports (if/else/endif, for/endfor via end); avoid foreign template dialects.","Lint the template by compiling it in a test before deploying."],"exampleFix":"# before: unclosed block, unknown tag\nTemplite('{% for x in xs %}{{ x }}')      # -> TempliteSyntaxError\nTemplite('{% bob %}')                     # unknown keyword\n\n# after: close blocks, use supported tags\nTemplite('{% for x in xs %}{{ x }}{% end %}')\nTemplite('{% if x %}yes{% else %}no{% end %}')","handlingStrategy":"validation","validationCode":"import re\nTAG = re.compile(r'\\{%.*?%\\}|\\{\\{.*?\\}\\}')\ndef lint_template(text):\n    for m in TAG.finditer(text):\n        tok = m.group()\n        if tok.startswith('{%') and not tok.strip().endswith('%}'):\n            return (False, 'unclosed tag: %r' % tok)\n    return True, ''\n\nok, why = lint_template(tpl)\nif not ok:\n    raise ValueError(why)\nTemplite(tpl)","typeGuard":"def is_balanced(text):\n    return text.count('{%') == text.count('%}') and text.count('{{') == text.count('}}')","tryCatchPattern":"try:\n    t = Templite(source, **context)\nexcept TempliteSyntaxError as e:\n    log.error('template syntax error: %s', e)\n    raise","preventionTips":["Compile templates in unit tests, not lazily at first request.","Pair every {% if %}/{% for %} with the engine's {% end %} (check dialect).","Restrict variable names to the Python-identifier regex the engine enforces.","Echo the offending %r token from the exception into your editor to jump to it."],"tags":[],"backgroundTag":null,"analyzedSha":"fba689d101eb5600f5c8f4d7fd79912498e950e2","analyzedAt":"2026-08-13T06:26:32.792Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}