aosabook/500lines · error · NameError

name ' ' 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.

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.

Appendix: 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)