nodejs/node · error · TemplateSyntaxError

chunk after expression

Error message

chunk after expression

What it means

Raised by Environment.compile_expression (jinja2 environment.py) when the source string parses to one valid expression but has leftover tokens after it. compile_expression expects exactly a single expression; after parsing, the stream must be at end-of-stream. Any trailing token — a second expression, an operator, or stray text — is rejected.

Source

Thrown at tools/inspector_protocol/jinja2/environment.py:626

        True

        Per default the return value is converted to `None` if the
        expression returns an undefined value.  This can be changed
        by setting `undefined_to_none` to `False`.

        >>> env.compile_expression('var')() is None
        True
        >>> env.compile_expression('var', undefined_to_none=False)()
        Undefined

        .. versionadded:: 2.1
        """
        parser = Parser(self, source, state='variable')
        exc_info = None
        try:
            expr = parser.parse_expression()
            if not parser.stream.eos:
                raise TemplateSyntaxError('chunk after expression',
                                          parser.stream.current.lineno,
                                          None, None)
            expr.set_environment(self)
        except TemplateSyntaxError:
            exc_info = sys.exc_info()
        if exc_info is not None:
            self.handle_exception(exc_info, source_hint=source)
        body = [nodes.Assign(nodes.Name('result', 'store'), expr, lineno=1)]
        template = self.from_string(nodes.Template(body, lineno=1))
        return TemplateExpression(template, undefined_to_none)

    def compile_templates(self, target, extensions=None, filter_func=None,
                          zip='deflated', log_function=None,
                          ignore_errors=True, py_compile=False):
        """Finds all the templates the loader can find, compiles them
        and stores them in `target`.  If `zip` is `None`, instead of in a
        zipfile, the templates will be stored in a directory.
        By default a deflate zip algorithm is used. To switch to

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Pass exactly one expression; split compound inputs into multiple compile_expression calls.
  2. Strip trailing junk / normalize user input before compiling.
  3. For full Jinja syntax use Environment.compile / from_string instead of compile_expression.

Example fix

# before
expr = env.compile_expression('a b')
# after
expr = env.compile_expression('a')
expr2 = env.compile_expression('b')
Defensive patterns

Strategy: validation

Validate before calling

from jinja2 import Environment
env = Environment()
def compile_single(source):
    # reject compound / multi-expression input early
    if any(sep in source for sep in (';', ',')) and source.count(' ') > 1:
        raise ValueError('compile_expression takes exactly one expression')
    return env.compile_expression(source)

Try / catch

try:
    expr = env.compile_expression(source)
except Exception as e:
    if 'chunk after expression' in str(e):
        raise ValueError('provide exactly one expression: %r' % source)
    raise

Prevention

When it happens

Trigger: Passing `'a b'`, `'a; b'`, `'a + b c'`, `'a == b =='`, or any source with two expressions / dangling operators to compile_expression; concatenating user fragments without separators; treating compile_expression like a full-statement compiler.

Common situations: Building a rule/eval engine on top of compile_expression and joining fragments with spaces; passing a Jinja statement (`{% if %}...`) instead of an expression; trailing whitespace is fine but trailing tokens are not.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/099eb6dfb1c65465. Report an issue: GitHub.