aosabook/500lines · error · NameError

global name '%s' is not defined

Error message

global name '%s' is not defined

What it means

Raised by byte_LOAD_GLOBAL when a name the compiler marked as global is absent from both frame.f_globals and frame.f_builtins. Unlike LOAD_NAME, the fast-local dict is skipped entirely; global lookups check only the module's globals and the builtins namespace. This matches CPython's NameError for names the compiler knows are module/builtin level (anything not assigned inside the function).

Source

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

        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):
        self.frame.f_locals[name] = self.pop()

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

    ## Operators

    UNARY_OPERATORS = {
        'POSITIVE': operator.pos,
        'NEGATIVE': operator.neg,
        'NOT':      operator.not_,
        'INVERT':   operator.invert,
    }

    def unaryOperator(self, op):
        x = self.pop()
        self.push(self.UNARY_OPERATORS[op](x))

    BINARY_OPERATORS = {
        'POWER':    pow,
        'MULTIPLY': operator.mul,

View on GitHub (pinned to fba689d101)

Solutions

  1. Import or define the missing name at module scope so it lands in frame.f_globals.
  2. If the name is a builtin, correct the spelling so it resolves through frame.f_builtins.
  3. Pass the dependency in as an explicit argument instead of relying on the global lookup.

Example fix

// before
def f():
    return helper()   # LOAD_GLOBAL -> NameError (helper never imported)
// after
from utils import helper
def f():
    return helper()
Defensive patterns

Strategy: try-catch

Validate before calling

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

for instr in dis.get_instructions(code):
    if instr.opname == 'LOAD_GLOBAL' and not global_resolvable(instr.argval, frame):
        print('missing global:', instr.argval)

Try / catch

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

Prevention

When it happens

Trigger: A function references a name treated as global (never assigned in the function, hence LOAD_GLOBAL) that was never imported or defined at module scope and is not a builtin, e.g. calling a helper defined in another module that was never imported into the running module's globals.

Common situations: Forgetting to import a module-level function/class used inside a function; a `del` that removed the global; a typo in a builtin name (e.g. `lenght`); running the function against a different module's globals dict than expected.

Related errors


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