nodejs/node · error · TypeError

can't create custom node types

Error message

can't create custom node types

What it means

NodeType.__new__ is monkey-patched to _failing_new at the end of nodes.py, so any attempt to create a new instance of NodeType or any subclass that does not override __new__ raises TypeError('can't create custom node types'). This is a deliberate guard: the Jinja2 AST node set is closed; only nodes defined inside jinja2.nodes are constructible, and user code is not allowed to mint custom node types.

Source

Thrown at tools/inspector_protocol/jinja2/nodes.py:998

    Example to change the `autoescape` setting::

        EvalContextModifier(options=[Keyword('autoescape', Const(True))])
    """
    fields = ('options',)


class ScopedEvalContextModifier(EvalContextModifier):
    """Modifies the eval context and reverts it later.  Works exactly like
    :class:`EvalContextModifier` but will only modify the
    :class:`~jinja2.nodes.EvalContext` for nodes in the :attr:`body`.
    """
    fields = ('body',)


# make sure nobody creates custom nodes
def _failing_new(*args, **kwargs):
    raise TypeError('can\'t create custom node types')
NodeType.__new__ = staticmethod(_failing_new); del _failing_new

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Do not subclass Jinja2 nodes; instead represent custom logic with existing node types or via extensions that hook the compiler.
  2. If you need a marker class, subclass object (or a plain base) rather than NodeType.
  3. For (de)serialization, use a format that does not reconstruct nodes via __new__ (e.g. recompile source rather than pickling ASTs).
  4. If absolutely necessary for a fork, override __new__ on your subclass to call object.__new__ - unsupported and version-fragile.

Example fix

// before
class MyNode(nodes.Expr):
    fields = ('value',)
instance = MyNode()  # raises
// after
class MyMarker(object):  # not a Jinja2 node
    pass
# express custom behavior through an extension + existing node types instead
Defensive patterns

Strategy: validation

Validate before calling

from jinja2 import nodes
import typing
cls = MyCandidateClass
if isinstance(cls, type) and issubclass(cls, nodes.NodeType):
    raise TypeError('do not subclass jinja2 NodeType; Jinja2 nodes are a closed set')

Type guard

def is_jinja_node_class(cls) -> bool:
    from jinja2 import nodes
    return isinstance(cls, type) and issubclass(cls, nodes.NodeType)

Try / catch

# n/a - the failing __new__ is intentional; do not catch
# fix the design instead of subclassing NodeType

Prevention

When it happens

Trigger: Defining a subclass of nodes.Node / nodes.Expr and trying to instantiate it (the subclass inherits the failing __new__). Calling NodeType() directly. A pickling/unpickling round-trip that invokes __new__ for an unknown node subclass registered externally.

Common situations: Extensions or compiler plugins that attempt to introduce new AST node types. Copy/paste of node definitions expecting them to be instantiable. PyInstaller / multiprocessing spawning that rebuilds nodes via __new__.

Related errors


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