nodejs/node · error · TypeError

Can't compile non template nodes

Error message

Can't compile non template nodes

What it means

Raised by compiler.generate (jinja2 compiler.py) when the AST node handed to the code generator is not an instance of nodes.Template. generate() expects the whole template AST (whose root is always a Template node produced by the parser); passing any other node type — a single statement, an expression, or a list — is a programmer error.

Source

Thrown at tools/inspector_protocol/jinja2/compiler.py:78

    supports_yield_from = True


def optimizeconst(f):
    def new_func(self, node, frame, **kwargs):
        # Only optimize if the frame is not volatile
        if self.optimized and not frame.eval_ctx.volatile:
            new_node = self.optimizer.visit(node, frame.eval_ctx)
            if new_node != node:
                return self.visit(new_node, frame)
        return f(self, node, frame, **kwargs)
    return update_wrapper(new_func, f)


def generate(node, environment, name, filename, stream=None,
             defer_init=False, optimized=True):
    """Generate the python source for a node tree."""
    if not isinstance(node, nodes.Template):
        raise TypeError('Can\'t compile non template nodes')
    generator = environment.code_generator_class(environment, name, filename,
                                                 stream, defer_init,
                                                 optimized)
    generator.visit(node)
    if stream is None:
        return generator.stream.getvalue()


def has_safe_repr(value):
    """Does the node have a safe representation?"""
    if value is None or value is NotImplemented or value is Ellipsis:
        return True
    if type(value) in (bool, int, float, complex, range_type, Markup) + string_types:
        return True
    if type(value) in (tuple, list, set, frozenset):
        for item in value:
            if not has_safe_repr(item):
                return False

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Wrap your node(s) in nodes.Template(body=[...], lineno=1) before calling generate.
  2. Prefer the public Environment.compile(source) / env.from_string(), which parse correctly into a Template node.
  3. If transforming an existing AST, operate on template.body but recompile via the Template root.

Example fix

# before
code = generate(nodes.Output([nodes.Data('hi')]), env, 'x', 'x.html')
# after
tpl = nodes.Template(body=[nodes.Output([nodes.Data('hi')])], lineno=1)
code = generate(tpl, env, 'x', 'x.html')
Defensive patterns

Strategy: validation

Validate before calling

from jinja2 import nodes, compiler

def safe_generate(node, env, name, filename, **kw):
    if not isinstance(node, nodes.Template):
        node = nodes.Template(body=[node], lineno=1)
    return compiler.generate(node, env, name, filename, **kw)

Type guard

from jinja2 import nodes
def is_template_node(node) -> bool:
    return isinstance(node, nodes.Template)

Prevention

When it happens

Trigger: Calling jinja2.compiler.generate() directly with a bare node (e.g. nodes.Output, nodes.For, nodes.Assign) instead of a nodes.Template wrapping it; constructing an AST by hand and forgetting the Template wrapper; calling the compiler on a sub-tree extracted from a parsed template.

Common situations: Library/integration authors building custom Jinja2 tooling (linters, optimizers, transformers) that pass subtrees to the compiler; misuse of the internal compile pipeline instead of Environment.compile.

Related errors


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