aosabook/500lines · error · NameError

name '%s' is not defined

Error message

name '%s' is not defined

What it means

Raised by byte_LOAD_NAME after the interpreter searched frame.f_locals, frame.f_globals, and frame.f_builtins without finding the name. This byterun-style VM mirrors CPython's NameError for lookups that start in the local scope (module bodies, class bodies, exec'd code). LOAD_NAME is the opcode emitted for those scopes, so any unbound name there reaches this raise.

Source

Thrown at interpreter/code/byterun/simple_python_interpreter.py:232

        self.push(const)

    def byte_POP_TOP(self):
        self.pop()

    def byte_DUP_TOP(self):
        self.push(self.top())

    ## Names
    def byte_LOAD_NAME(self, name):
        frame = self.frame
        if name in frame.f_locals:
            val = frame.f_locals[name]
        elif name in frame.f_globals:
            val = frame.f_globals[name]
        elif name in frame.f_builtins:
            val = frame.f_builtins[name]
        else:
            raise NameError("name '%s' is not defined" % name)
        self.push(val)

    def byte_STORE_NAME(self, name):
        self.frame.f_locals[name] = self.pop()

    def byte_DELETE_NAME(self, name):
        del self.frame.f_locals[name]

    def byte_LOAD_FAST(self, name):
        if name in self.frame.f_locals:
            val = self.frame.f_locals[name]
        else:
            raise UnboundLocalError(
                "local variable '%s' referenced before assignment" % name
            )
        self.push(val)

    def byte_STORE_FAST(self, name):

View on GitHub (pinned to fba689d101)

Solutions

  1. Confirm the name is defined or imported at module scope before the bytecode runs (inspect frame.f_globals).
  2. If the name should be a builtin, verify frame.f_builtins is populated with the builtins module.
  3. Use dis.dis() on the code object to find the offending LOAD_NAME and compare it to the namespaces you expect to be in scope.
  4. Wrap the interpreter run in a try/except NameError to log the offending name and continue.

Example fix

// before
print(undefined_name)   # LOAD_NAME -> NameError
// after
undefined_name = 42
print(undefined_name)
Defensive patterns

Strategy: try-catch

Validate before calling

def name_resolvable(name, frame):
    return name in frame.f_locals or name in frame.f_globals or name in frame.f_builtins

# before running the code object
for instr in dis.get_instructions(code):
    if instr.opname == 'LOAD_NAME' and not name_resolvable(instr.argval, frame):
        print('missing name:', instr.argval)

Try / catch

try:
    interpreter.run_frame(frame)
except NameError as e:
    log.warning('undefined name during exec: %s', e)

Prevention

When it happens

Trigger: Executing bytecode whose LOAD_NAME target was never bound: a top-level name referenced at module scope that has no entry in f_locals/f_globals and is not a builtin; a name that was just removed with DELETE_NAME; running code compiled for a different module than the one whose globals dict is loaded into the frame.

Common situations: Typo in a module-level variable or function name; a top-level import that was placed inside a conditional branch that never ran; referencing a name before its module-level assignment; a failed/missing import so the name never lands in f_globals.

Related errors


AI-assisted analysis of aosabook/500lines@fba689d101 (2026-08-13). Data as JSON: /api/errors/436059c7463cba5c. Report an issue: GitHub.