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
NameErrorin Python - Reproduce every common variant with clear, minimal examples
- Fix each cause with the right pattern
- Prevent
NameErrorfrom appearing in your code again
Page Contents
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, andopenare 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:
| Error | Cause | Example |
|---|---|---|
NameError | Name not defined in any scope | print(x) when x does not exist |
TypeError | Operation on wrong type | "string" + 1 |
AttributeError | Attribute not found on object | None.upper() |
IndexError | Sequence index out of range | [1, 2][10] |
KeyError | Dictionary 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:
- Python null vs None: Complete Guide to Handling Null Values — Understanding None prevents many NameError-like bugs caused by missing return values.
- Python Exception Handling: Patterns and Best Practices — Use try/except to gracefully handle NameError and other runtime exceptions.
- Introduction to Python Programming (2026 Edition) — A beginner-friendly overview of Python fundamentals, including variables and scope.

