Fix NameError: Python undefined name resolution at runtime

Python beginner All platforms (Windows, macOS, Linux) Python 3.x Python 2.7 (legacy)

1. Symptoms

When a NameError occurs in Python, the interpreter halts execution and displays a traceback that clearly identifies the problem. The error message follows a consistent pattern: NameError: name 'identifier' is not defined, where identifier is the name that Python could not resolve.

Common manifestations:

Traceback (most recent call last):
  File "example.py", line 10, in <module>
    print(my_variable)
NameError: name 'my_variable' is not defined
Traceback (most recent call last):
  File "calculator.py", line 15, in <module>
    result = add_numbers(a, b)
NameError: name 'add_numbers' is not defined

The error always appears at the exact line where Python attempts to access the undefined name. The line number in the traceback pinpoints the location, making initial diagnosis straightforward. However, the root cause might be earlier in the code—perhaps a typo made hours ago that only manifests when execution reaches the problematic line.

Typical symptoms include:

  • Unexpected NameError during script execution
  • Code that worked previously suddenly failing
  • Errors appearing only under certain conditions
  • Errors in imported modules referencing names not defined in those modules

2. Root Cause

Python’s NameError occurs during the execution phase when the interpreter attempts to resolve a name that has not been defined in the current scope. Python uses a LEGB rule for name resolution: Local → Enclosing → Global → Built-in. When a name cannot be found in any of these scopes, Python raises NameError.

Primary causes:

  1. Typographical errors in variable names - The most common cause. Python is case-sensitive, so MyVariable, myvariable, and my_variable are three distinct names.

  2. Using a variable before assignment - Referencing a variable in a function before it has been assigned a value.

  3. Missing import statements - Attempting to use functions from modules that have not been imported.

  4. Scope-related issues - Trying to access variables defined in different scopes.

  5. Conditional definition - Variables defined only inside conditional blocks that weren’t executed.

  6. Misspelled built-in functions - Accidentally using pint() instead of print().

  7. Class or function not yet defined - Calling functions or instantiating classes defined later in the code (when not using forward references).

  8. Circular imports - Import issues that manifest as NameError when modules reference each other.

Understanding why NameError occurs requires examining Python’s two-phase execution model: first the compiler performs syntax checking and creates bytecode, then the interpreter executes the bytecode. Name resolution happens exclusively during execution, which is why NameError is a runtime error rather than a compile-time error.

3. Step-by-Step Fix

Step 1: Identify the undefined name

The error message clearly states which name is undefined. Look for the specific identifier between quotes in name 'identifier' is not defined.

Step 2: Locate all occurrences of the name

Search your codebase for the problematic identifier to understand where it’s used and where it should be defined.

Step 3: Determine the intended value or definition

Decide whether this should be a variable, function, class, or imported module member.

Step 4: Apply the appropriate fix

Fix 1: Define the variable

# BROKEN CODE
def calculate_total():
    subtotal = 100
    tax = 10
    return total  # NameError: name 'total' is not defined

result = calculate_total()
print(result)

Before:

def calculate_total():
    subtotal = 100
    tax = 10
    return total  # NameError: name 'total' is not defined

result = calculate_total()
print(result)

After:

def calculate_total():
    subtotal = 100
    tax = 10
    total = subtotal + tax  # Define 'total' before using it
    return total

result = calculate_total()
print(result)  # Output: 110

Fix 2: Add missing import statement

# BROKEN CODE
def format_date(date_obj):
    return date_obj.strftime("%Y-%m-%d")

today = datetime.now()  # NameError: name 'datetime' is not defined
print(format_date(today))

Before:

def format_date(date_obj):
    return date_obj.strftime("%Y-%m-%d")

today = datetime.now()
print(format_date(today))

After:

from datetime import datetime  # Import statement added

def format_date(date_obj):
    return date_obj.strftime("%Y-%m-%d")

today = datetime.now()
print(format_date(today))  # Output: 2024-01-15

Fix 3: Correct typos

# BROKEN CODE
def calculate_area(width, height):
    return width * haight  # Typo: 'haight' instead of 'height'

area = calculate_area(5, 10)
print(f"Area: {area}")

Before:

def calculate_area(width, height):
    return width * haight  # Typo

area = calculate_area(5, 10)
print(f"Area: {area}")

After:

def calculate_area(width, height):
    return width * height  # Fixed typo

area = calculate_area(5, 10)
print(f"Area: {area}")  # Output: Area: 50

Fix 4: Handle conditional variable definition

# BROKEN CODE
def get_discount_price(price, is_member):
    if is_member:
        discount_price = price * 0.9
    return discount_price  # NameError if is_member is False

final_price = get_discount_price(100, False)
print(final_price)

Before:

def get_discount_price(price, is_member):
    if is_member:
        discount_price = price * 0.9
    return discount_price  # NameError if is_member is False

final_price = get_discount_price(100, False)
print(final_price)

After:

def get_discount_price(price, is_member):
    discount_price = price  # Initialize with default value
    if is_member:
        discount_price = price * 0.9
    return discount_price

final_price = get_discount_price(100, False)
print(final_price)  # Output: 100

4. Verification

After applying the fix, verify the solution by running the code again:

python example.py

Expected output: The script should execute without any NameError traceback.

Verification checklist:

  1. Run the specific test case that previously triggered the error
  2. Test edge cases including False, None, empty collections, and zero values
  3. Check all code paths to ensure no other NameError instances exist
  4. Run unit tests if available: python -m pytest or python -m unittest
  5. Use a linter to catch potential issues: python -m py_compile your_script.py

Automated verification script:

def verify_fix():
    """Run the code that previously raised NameError."""
    try:
        # Replace with the code that was failing
        from datetime import datetime
        today = datetime.now()
        result = today.strftime("%Y-%m-%d")
        print(f"Success: Date formatted as {result}")
        return True
    except NameError as e:
        print(f"NameError still present: {e}")
        return False

if __name__ == "__main__":
    verify_fix()

IDE-based verification:

Most modern IDEs (VS Code, PyCharm, etc.) highlight undefined names with red underlines in real-time. If your IDE doesn’t show this, ensure you have Pylint or a similar linter installed and enabled.

5. Common Pitfalls

Pitfall 1: Case sensitivity

Python is case-sensitive. True, TRUE, and true are three different identifiers. Built-in constants like True, False, and None must use exact casing.

# BROKEN
is_active = TRUE  # NameError: name 'TRUE' is not defined

# CORRECT
is_active = True  # Built-in constant

Pitfall 2: Global vs. local scope

Variables defined outside functions are global; variables defined inside functions are local. Attempting to read a local variable before assignment raises NameError.

# BROKEN
def process_data():
    print(data)  # NameError: data referenced before assignment
    data = [1, 2, 3]

# CORRECT
def process_data():
    data = [1, 2, 3]  # Define before use
    print(data)

process_data()  # Output: [1, 2, 3]

Pitfall 3: Circular imports

Module A imports from Module B while Module B imports from Module A, causing names to be undefined at runtime.

# module_a.py
from module_b import helper  # May fail if module_b hasn't finished loading

# module_b.py
from module_a import processor  # Both modules trying to import each other

Solution: Restructure imports, use late imports inside functions, or use absolute imports with proper package structure.

Pitfall 4: Function name shadowing

Naming a variable the same as a built-in function can cause confusion.

# BROKEN
list = [1, 2, 3]  # Shadows built-in 'list'
numbers = list(range(5))  # NameError: 'list' is now a variable, not a function

# CORRECT
numbers_list = [1, 2, 3]  # Don't shadow built-ins
numbers = list(range(5))

Pitfall 5: String quotes vs. variable names

Beginners sometimes forget that names inside quotes are strings, not variable references.

# BROKEN
variable_name = "value"
print("variable_name")  # Prints the string, not the variable

# CORRECT
variable_name = "value"
print(variable_name)  # Prints "value"

Pitfall 6: String formatting errors

Using incorrect f-string syntax can lead to unexpected behavior.

# BROKEN
name = "Alice"
print(f"Hello, {name}")  # This works correctly
print(f"Hello, {name}")  # Missing 'f' prefix - treats as regular string

UnboundLocalError

A subclass of NameError that specifically indicates a local variable was referenced before assignment within a function. Python treats variables assigned within a function as local, so reading them before assignment raises this specific error.

def example():
    print(x)  # UnboundLocalError: local variable 'x' referenced before assignment
    x = 10

example()

NameError: name ‘…’ is not defined

The exact error message format. Variations include:

  • NameError: name 'None' is not defined (incorrect use of None)
  • NameError: name '__name__' is not defined (context-specific built-ins)

AttributeError

Often confused with NameError when accessing attributes. If the base object doesn’t exist, you’ll see NameError; if the attribute doesn’t exist on a valid object, you’ll see AttributeError.

# NameError if 'non_existent_module' doesn't exist
# AttributeError if the module exists but lacks the attribute
import os
os.non_existent_function()  # AttributeError: module 'os' has no attribute 'non_existent_function'

ImportError

Manifests when trying to import names that don’t exist in the target module. This can appear as NameError in imported code.

from collections import OrderedDict  # Works
from collections import ChainMap  # ImportError: cannot import name 'ChainMap' (in older Python versions)

Key differences:

Error Cause Resolution
NameError Name not defined in any scope Define the variable or import it
UnboundLocalError Local variable used before assignment Initialize before use
AttributeError Attribute doesn’t exist on object Check object type or attribute name
ImportError Module or name doesn’t exist Verify module installation or name

Prevention strategies:

  1. Use IDE with real-time error checking
  2. Run linters (Pylint, Flake8) in your CI/CD pipeline
  3. Write unit tests to catch undefined references
  4. Follow PEP 8 naming conventions consistently
  5. Use type hints (Python 3.5+) to catch naming issues early
# Type hints can help catch errors
def greet(name: str) -> str:
    return f"Hello, {nmae}"  # IDE may catch this typo if configured

# Refactored with correct name
def greet(name: str) -> str:
    return f"Hello, {name}"