nodejs/node · error · TypeError

Can't create internal names. Use the `free_identifier` meth

Error message

Can't create internal names.  Use the `free_identifier` method on a parser.

What it means

Raised by jinja2.nodes.InternalName.__init__ to forbid external construction of InternalName AST nodes. InternalName represents compiler-allocated scratch variables produced only by Parser.free_identifier(); allowing user code to mint them would break the compiler's identifier tracking. The constructor unconditionally raises TypeError.

Source

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

    """If created with an import name the import name is returned on node
    access.  For example ``ImportedName('cgi.escape')`` returns the `escape`
    function from the cgi module on evaluation.  Imports are optimized by the
    compiler so there is no need to assign them to local variables.
    """
    fields = ('importname',)


class InternalName(Expr):
    """An internal name in the compiler.  You cannot create these nodes
    yourself but the parser provides a
    :meth:`~jinja2.parser.Parser.free_identifier` method that creates
    a new identifier for you.  This identifier is not available from the
    template and is not threated specially by the compiler.
    """
    fields = ('name',)

    def __init__(self):
        raise TypeError('Can\'t create internal names.  Use the '
                        '`free_identifier` method on a parser.')


class MarkSafe(Expr):
    """Mark the wrapped expression as safe (wrap it as `Markup`)."""
    fields = ('expr',)

    def as_const(self, eval_ctx=None):
        eval_ctx = get_eval_context(self, eval_ctx)
        return Markup(self.expr.as_const(eval_ctx))


class MarkSafeIfAutoescape(Expr):
    """Mark the wrapped expression as safe (wrap it as `Markup`) but
    only if autoescaping is active.

    .. versionadded:: 2.5
    """

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Use parser.free_identifier() on an active Parser instance to obtain a valid InternalName instead of constructing one.
  2. When deep-copying ASTs, special-case InternalName to copy the instance via object.__new__ rather than calling __init__.
  3. In tests, obtain InternalName instances from a real parsed template rather than constructing them.
  4. If you must instantiate for a transform, bypass with object.__new__(nodes.InternalName) and set .name manually - but prefer free_identifier.

Example fix

// before
node = nodes.InternalName()
node.name = 'tmp_0'
// after
# during parsing/transformation with an active parser `parser`
ident = parser.free_identifier()  # returns a fully-formed InternalName
Defensive patterns

Strategy: validation

Validate before calling

from jinja2 import nodes
# never call nodes.InternalName() directly; obtain from a parser
# (placeholder check - real identifiers come from Parser.free_identifier)
import inspect
if inspect.stack()[1].function == '<module>':
    raise RuntimeError('do not construct InternalName; use parser.free_identifier()')

Type guard

def is_internal_name(node) -> bool:
    return isinstance(node, nodes.InternalName)

Try / catch

# n/a - construction is a programming error; catch should not mask it
# fix the call site instead of try/except

Prevention

When it happens

Trigger: Calling nodes.InternalName() directly in code that builds or manipulates the Jinja2 AST (e.g. a custom optimizer, transformer, or test harness). Copy/deepcopy of an AST that re-invokes __init__ on an InternalName instance. metaprogramming that enumerates node subclasses and instantiates each.

Common situations: Third-party extensions that walk and rebuild the node tree. Test fixtures that try to round-trip every node type. Tools that serialize/deserialize the AST and reconstruct nodes via their __init__.

Related errors


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