New in 2026: Master Python for AI, Data Science

Python

NameError: name ‘x’ is not defined — Python Error Causes and Fix

NameError: name 'x' is not defined — Python Error Causes and How to Fix It

You ran your Python code and it crashed with NameError: name 'x' is not defined. You checked the spelling — it looks right. You defined it two lines ago. Python disagrees. Here is exactly why it happens and how to fix it for good.

In this guide, you will learn to:

  • Understand exactly what causes NameError in Python
  • Reproduce every common variant with clear, minimal examples
  • Fix each cause with the right pattern
  • Prevent NameError from appearing in your code again

What Is a NameError in Python?

A NameError occurs when Python tries to access a variable, function, or class name that does not exist in the current scope. Unlike languages that compile variable declarations, Python resolves names at runtime — if a name has never been assigned or imported, Python raises NameError when it hits that line.

When you run a script that references an undefined name, Python stops and prints the error:

x  # NameError: name 'x' is not defined

The error message always tells you exactly which name Python could not find. Use it — it is specific for a reason.

Cause 1: The Variable Was Never Defined

This is the most straightforward cause. You referenced a variable before assigning it:

# This will raise NameError
print(y)  # NameError: name 'y' is not defined

y = 10    # Assignment comes AFTER the reference
print(y)  # This works

The fix is simple: move the assignment before the first use:

y = 10    # Define first
print(y)  # Works: 10

Cause 2: A Function Returns Nothing (Returns None)

This is one of the most common sources of confusion for intermediate developers. A function that does not explicitly return a value returns None. If you then try to use the result as a variable, you may get unexpected results or errors:

def get_user_email(username):
    # Forgot to return the email
    print(f"Looking up {username}")

result = get_user_email("ada")
print(result)  # None — the function returned nothing

# Trying to access a field on None
print(result.upper())  # AttributeError: 'NoneType' object has no attribute 'upper'

The fix is to always return a value explicitly, or handle None before using it:

def get_user_email(username):
    emails = {
        "ada": "[email protected]",
        "grace": "[email protected]",
    }
    return emails.get(username)  # Explicitly return None if missing

result = get_user_email("ada")
if result is not None:
    print(result.upper())  # Safe

Cause 3: Typos and Case Sensitivity

Python is case-sensitive. Count, count, and COUNT are three completely different names:

count = 0
print(Count)  # NameError: name 'Count' is not defined
              # Python sees 'Count' as a different name

Typos in variable names also cause NameError. Python cannot guess what you meant — it only knows what you wrote:

user_name = "Alice"
print(user_name)  # Works
print(username)   # NameError: name 'username' is not defined
                  # Note: 'user_name' != 'username'

Cause 4: Using a Variable Before It Is Defined in the Same Scope

Even if a variable is defined later in the same function, Python raises NameError if you reference it before the assignment runs:

def process():
    print(total)  # NameError: local variable 'total' referenced before assignment
    total = 100
    return total

Python compiles the entire function before running it. It sees that total is assigned inside the function, so it treats total as a local variable. When the function runs and hits print(total), Python looks for a local total — which has not been assigned yet. The result is a NameError even though the line total = 100 appears just a few lines below.

The fix is to either define the variable before use or declare it as global if you intend to use a global variable:

# Fix option 1: Define before use
def process():
    total = 100
    print(total)  # Works: 100
    return total

# Fix option 2: Use global if you need the module-level variable
total = 50

def process():
    global total
    print(total)  # Works: 50 — reads the global
    total = 100   # Overwrites the global
    return total

Cause 5: Forgetting to Import a Module or Function

Python has an extensive standard library, but you must explicitly import what you want to use. Without an import statement, Python does not know where to find the name:

# Without import — NameError
result = random.randint(1, 10)  # NameError: name 'random' is not defined

# With import — works
import random
result = random.randint(1, 10)  # Works

Common imports that beginners forget:

# Forgetting the entire import
from collections import defaultdict  # Must import what you use
my_dict = defaultdict(int)

# Importing the module but not the specific name
import random
choice = random.choice([1, 2, 3])  # Works — random is the module
# vs
from random import choice
choice([1, 2, 3])  # Works — choice is imported directly

Cause 6: Variable Scope in Nested Functions (Local vs Enclosing)

Python has nested scope rules: LEGB — Local, Enclosing, Global, Built-in. A name defined in an outer function is not automatically visible inside an inner function:

def outer():
    message = "Hello from outer"
    
    def inner():
        print(message)  # Works — 'message' is in enclosing scope
    
    inner()

outer()  # Works: Hello from outer

But if you try to assign to a name from an enclosing scope inside the inner function without declaring it, Python treats it as a local variable — and the assignment happens after the reference, causing a NameError:

def outer():
    message = "Hello from outer"
    
    def inner():
        print(message)  # NameError: cannot access local 'message'
                         # Python sees 'message' is assigned below,
                         # so it is local. But it has not been assigned yet.
        message = "Changed in inner"
    
    inner()

outer()

Use the nonlocal keyword to modify a variable from an enclosing scope:

def outer():
    message = "Hello from outer"
    
    def inner():
        nonlocal message
        print(message)  # Works: Hello from outer
        message = "Changed in inner"
    
    inner()
    print(message)  # Works: Changed in inner

outer()

Cause 7: Misspelled Built-in Names

Python has many built-in functions and constants that beginners sometimes misspell. These are always available without importing — but only if you spell them correctly:

Truue = True    # Misspelled — creates a new variable, not the builtin
if Truue:        # Works but shadows the builtin
    print("hello")

# Common misspelling: None vs none
result = none    # NameError: name 'none' is not defined
                 # Python's null is spelled None (capital N)

# Another common one
len([1, 2, 3])   # Correct
leng([1, 2, 3])  # NameError: name 'leng' is not defined

Cause 8: Accidental Overwriting of Built-ins

Python lets you assign to any name — including built-in function names. This can silently break things:

len = 10   # Overwrote the built-in len function
print(len)  # 10 — not a function anymore!

# Now this breaks:
print(len([1, 2, 3]))  # TypeError: 'int' object is not callable

If you accidentally overwrite a built-in and get an error later, simply reassign or restart your Python session. Built-ins are always available in a fresh environment. To check if a name is a built-in:

import builtins
print("len" in dir(builtins))  # True — len is a builtin

# Restore a overwritten builtin
len = builtins.len  # Or restart your REPL/script

How to Debug NameError: A Step-by-Step Checklist

When you encounter a NameError, work through this checklist in order:

  • Check the error message — it tells you exactly which name was not found. Look at the line number too.
  • Search backward from the error line — is the name assigned before the line that references it?
  • Check for typos — case sensitivity and spelling errors are the most common cause.
  • Check your imports — is the module imported? Is the specific name imported?
  • Check the scope — is the variable defined in the right function or module level?
  • Check for accidental built-in overwrites — list, dict, sum, max, min, type, id, file, input, and open are commonly overwritten.
  • Check the function return value — did the function actually return what you expected?

How to Prevent NameError in Python

Prevention is better than debugging. Here are the habits that eliminate NameError from your code:

Initialize All Variables Before Use

Define variables at the start of functions or modules before using them. This makes the code easier to read and guarantees Python can find every name:

# Good pattern — always initialize before logic
def calculate_stats(numbers):
    total = 0        # Initialize first
    count = 0        # Initialize first
    for n in numbers:
        total += n
        count += 1
    return total / count if count > 0 else 0

Use Type Checking with mypy

Install mypy and run it on your code before execution. mypy catches NameError-level issues at development time. See the mypy documentation for getting started:

pip install mypy
mypy your_script.py

Avoid Reusing Variable Names in Nested Scopes

Nested functions that share variable names with outer scopes are a common source of confusing bugs. Use distinct names or be explicit with nonlocal:

# Clear pattern — use nonlocal explicitly when you mean to modify outer scope
def counter(start=0):
    count = start
    
    def increment():
        nonlocal count
        count += 1
        return count
    
    return increment

c = counter(5)
print(c())  # 6
print(c())  # 7

Never Name Variables the Same as Built-ins

Get in the habit of never using list, dict, str, int, file, or id as variable names. Use alternatives like my_list, data_dict, user_str:

# Bad — overwrites built-in
list = [1, 2, 3]
print(list)  # [1, 2, 3] — list is now an int object

# Good — clear and does not shadow built-ins
numbers = [1, 2, 3]
print(numbers)  # [1, 2, 3] — built-in list is still available

The LEGB Rule: How Python Resolves Names

Python follows the LEGB rule to resolve any name. Understanding this helps you predict where a NameError will occur. The official Python documentation covers scope rules in Classes → Python Scopes and Namespaces:

# L — Local: inside the current function
def foo():
    x = 1  # x is local to foo()
    print(x)

# E — Enclosing: in the local scope of an enclosing function
def outer():
    x = 1  # x is in outer's local scope
    def inner():
        print(x)  # x found in enclosing scope (outer)
    inner()

# G — Global: at the module level
x = 1  # module-level x
def foo():
    print(x)  # x found in global scope

# B — Built-in: Python's built-in names (len, print, int, etc.)
print(len("hello"))  # len is a built-in

NameError vs Other Common Python Errors

NameError is often confused with other Python errors. Here is how to tell them apart:

ErrorCauseExample
NameErrorName not defined in any scopeprint(x) when x does not exist
TypeErrorOperation on wrong type"string" + 1
AttributeErrorAttribute not found on objectNone.upper()
IndexErrorSequence index out of range[1, 2][10]
KeyErrorDictionary key not found{"a": 1}["b"]

Frequently Asked Questions

Why does Python say “name ‘x’ is not defined” even though I defined it above?

Check the scope. If x is defined inside a function and you are referencing it outside that function (or in a different function), Python will raise NameError. Variables defined inside a function are local to that function only — they do not exist outside it. Move the definition to module level, or pass the value as an argument.

Why does Python say “name ‘x’ is not defined” inside a nested function even though I defined it in the outer function?

This happens when you both reference and assign to a name inside a nested function. Python sees the assignment and treats the name as local throughout the function — but the reference happens before the assignment runs. Use the nonlocal keyword before assigning to a name from an enclosing scope.

Why does Python say “name ‘x’ is not defined” after importing a module?

You likely imported the module as a whole (import random) but referenced a name without the module prefix (randint() instead of random.randint()), or you imported a submodule that was not installed. Use import random; random.randint(1, 10) or from random import randint; randint(1, 10).

How do I check if a variable exists before using it?

Use a try/except block around the code that might reference an undefined name, or initialize variables with sensible defaults. Python’s globals() and locals() dictionaries let you check whether a name is defined in a given scope:

if "x" in globals():
    print(x)
else:
    print("x is not defined at module level")

# Or use getattr with a default
x = getattr(some_object, "maybe_x", None)

Summary

NameError: name 'x' is not defined is Python’s way of telling you it looked everywhere in the current scope chain — local, enclosing, global, and built-in — and could not find the name you referenced. The most common causes are simple: a typo, a missing import, a function that returns None, or accidentally overwriting a built-in. Scope confusion — using global or nonlocal incorrectly — is the most common cause of confusing NameError in larger codebases.

The fix is almost always one of three things: define the name before using it, import the module or function you need, or correct the scope (local vs global vs nonlocal). Once you internalize Python’s LEGB rule, NameError becomes one of the easiest errors to prevent and debug.


Related Articles:

Related posts
Python

Pydantic Agent Basics: A Complete 2026 Tutorial

ProgrammingPython

Production-Ready MCP Servers — Security, Testing & Deployment

ProgrammingPython

Build Your First MCP Server with Python SDK — Fundamentals

ProgrammingPython

Connect FastAPI to MCP — Two Integration Patterns

Leave a Reply