aosabook/500lines · error · TempliteSyntaxError
%s: %r
Error message
%s: %r
What it means
Raised by Templite._syntax_error, the single chokepoint for all template-compilation errors. It formats a human-readable msg and the offending token via '%s: %r'. TempliteSyntaxError subclasses ValueError and is raised during Templite() construction (compile time), never at render time. Possible messages come from the parser: invalid variable names, malformed if/for/endif/endfor tags, too many ends, mismatched end tags, unknown tags, and unmatched action tags.
Source
Thrown at template-engine/code/templite.py:217
if "|" in expr:
pipes = expr.split("|")
code = self._expr_code(pipes[0])
for func in pipes[1:]:
self._variable(func, self.all_vars)
code = "c_%s(%s)" % (func, code)
elif "." in expr:
dots = expr.split(".")
code = self._expr_code(dots[0])
args = ", ".join(repr(d) for d in dots[1:])
code = "do_dots(%s, %s)" % (code, args)
else:
self._variable(expr, self.all_vars)
code = "c_%s" % expr
return code
def _syntax_error(self, msg, thing):
"""Raise a syntax error using `msg`, and showing `thing`."""
raise TempliteSyntaxError("%s: %r" % (msg, thing))
def _variable(self, name, vars_set):
"""Track that `name` is used as a variable.
Adds the name to `vars_set`, a set of variable names.
Raises an syntax error if `name` is not a valid name.
"""
if not re.match(r"[_a-zA-Z][_a-zA-Z0-9]*$", name):
self._syntax_error("Not a valid name", name)
vars_set.add(name)
def render(self, context=None):
"""Render this template by applying it to `context`.
`context` is a dictionary of values to use in this rendering.
View on GitHub (pinned to fba689d101)
Solutions
- Read the message: it names the problem ('Not a valid name', 'Don't understand for', etc.) and shows the token via %r.
- Make variable names match [_a-zA-Z][_a-zA-Z0-9]* (no hyphens, dots, or spaces).
- Match every {% if %}/{% for %} with exactly one {% endif %}/{% endfor %} of the matching type and add no extra ends.
- Remember only if/for/endif/endfor are supported; remove unsupported constructs.
Example fix
// before
Templite('Hi {{user-name}}') # Not a valid name: 'user-name'
Templite('{% if a b %}x{% endif %}') # Don't understand if
// after
Templite('Hi {{user_name}}')
Templite('{% if a %}x{% endif %}') Defensive patterns
Strategy: try-catch
Validate before calling
import re
NAME_RE = re.compile(r'[_a-zA-Z][_a-zA-Z0-9]*$')
def looks_valid(template):
for m in re.findall(r'{{(.+?)}}', template):
for part in m.split('|'):
head = part.split('.')[0].strip()
if head and not NAME_RE.match(head):
return False, head
return True, None Try / catch
try:
t = Templite(template_text)
except TempliteSyntaxError as e:
log.error('bad template: %s', e)
t = None Prevention
- Validate template strings in tests before deployment.
- Restrict variable names to [_a-zA-Z][_a-zA-Z0-9]* (no hyphens/dots/spaces).
- Remember only if/for/endif/endfor are supported; avoid unsupported Django tags.
- Pair every {% if %}/{% for %} with the matching end tag.
When it happens
Trigger: Constructing Templite(text) where text contains: a variable name failing the regex [_a-zA-Z][_a-zA-Z0-9]*$ (e.g. 'user-name'); an {% if %} without exactly one expression; a {% for %} not matching 'for var in expr'; extra {% endif %}/{% endfor %}; an {% endfor %} after an {% if %}; an unsupported {% tag %}; or a missing end tag at EOF.
Common situations: Hand-written templates with typos; copy-pasting Django syntax this nano-subset does not support (no {% else %}, no filter arguments); forgetting to close an {% if %}/{% for %}; using hyphens, dots, or spaces in variable names.
Related errors
- name '%s' is not defined
- local variable '%s' referenced before assignment
- global name '%s' is not defined
- fieldname
- fieldname
AI-assisted analysis of aosabook/500lines@fba689d101 (2026-08-13).
Data as JSON: /api/errors/e042fa40540730e2.
Report an issue: GitHub.