Engineering6 min read
Fix NameError in Python: "name 'X' is not defined" — 6 Causes and Fixes
Python NameError means the interpreter hit a name it doesn't recognize. Here are the 6 most common causes — typos, scope, missing imports — and the exact fix for each one.
What Is a NameError?#
Python raises NameError when it encounters a name — variable, function, or class — that hasn't been defined in the current scope.
Error: NameError: name 'user_data' is not defined
This error always means one of six things. Work through each cause below in order — most NameErrors are fixed by cause 1 or 2.
Cause 1: Typo in Variable Name#
Python is case-sensitive. UserData, user_data, and userdata are three different names. A single character difference causes NameError.
python
# ❌ Defined as user_data, referenced as userdata
user_data = fetch_user(user_id)
print(userdata['email']) # NameError: name 'userdata' is not defined
▎ Fix: Use your editor's "Go to Definition" (F12 in VS Code) on the erroring name. If it can't navigate, the name doesn't exist — check spelling
▎ against where it was defined.
# ✅ Names match
user_data = fetch_user(user_id)
print(user_data['email'])
Cause 2: Variable Used Before Assignment
Python executes top to bottom. Referencing a variable before the line that assigns it causes NameError.
# ❌ result used before it's assigned
def calculate_total(items):
print(f"Total: {result}") # NameError here
result = sum(item['price'] for item in items)
return result
▎ Fix: Move the reference after the assignment, or initialize the variable at the top of the function.
# ✅ Initialize first
def calculate_total(items):
result = sum(item['price'] for item in items)
print(f"Total: {result}")
return result
Cause 3: Variable Defined Inside a Conditional That Didn't Run
Variables assigned inside if blocks only exist if that branch executed. Referencing them outside is NameError waiting to happen.
# ❌ user only defined if API call succeeds
def get_username(user_id):
if user_id:
user = api.get_user(user_id)
return user.name # NameError if user_id was falsy
▎ Fix: Initialize the variable before the conditional with a sensible default.
# ✅ Always defined
def get_username(user_id):
user = None
if user_id:
user = api.get_user(user_id)
return user.name if user else 'Anonymous'
Cause 4: Scope Error — Variable Defined in Different Function
Variables defined inside a function are local to that function. They don't exist in other functions or at module level.
# ❌ config defined inside setup(), referenced outside
def setup():
config = load_config()
def run():
print(config['debug']) # NameError: config is not defined
setup()
run()
▎ Fix: Return the value and pass it where needed, or use a module-level variable.
# ✅ Pass through return value
def setup():
return load_config()
def run(config):
print(config['debug'])
config = setup()
run(config)
▎ Note: Using global to fix scope issues is a code smell. If you find yourself reaching for global, the function design needs refactoring — not a
▎ global variable.
Cause 5: Missing Import
Built-in modules (json, os, datetime) and third-party packages must be imported before use. Referencing them without importing raises NameError,
not ImportError.
# ❌ datetime used without import
def get_timestamp():
return datetime.now().isoformat() # NameError: name 'datetime' is not defined
▎ Fix: Add the import at the top of the file.
# ✅ Import first
from datetime import datetime
def get_timestamp():
return datetime.now().isoformat()
▎ Tip: VS Code with Pylance auto-detects missing imports. Hover over the red underline → "Quick Fix" → "Add import". Faster than typing it
▎ manually.
Cause 6: Name Defined in a Try Block, Used After
When an exception occurs inside a try block, assignment after the error point doesn't happen. Code after the try/except can reference a name that
was never set.
# ❌ connection only assigned if try succeeds
try:
connection = db.connect(DATABASE_URL)
cursor = connection.cursor()
except Exception as e:
print(f"DB error: {e}")
cursor.execute("SELECT * FROM users") # NameError if connect() failed
▎ Fix: Initialize variables before the try block, or move usage inside the try.
# ✅ Use inside try where it's guaranteed to exist
try:
connection = db.connect(DATABASE_URL)
cursor = connection.cursor()
cursor.execute("SELECT * FROM users")
return cursor.fetchall()
except Exception as e:
print(f"DB error: {e}")
return []
How to Find It Fast
Python's NameError stack trace points to the exact line. Read it bottom-up:
Traceback (most recent call last):
File "app.py", line 47, in process_order
total = calculate_discount(subtotal, promo_cide)
NameError: name 'promo_cide' is not defined. Did you mean: 'promo_code'?
Python 3.10+ includes "Did you mean?" suggestions. If you see that — it's a typo (Cause 1). Fix the name and move on.
For cross-file or cross-scope NameErrors, paste the error + surrounding function into DebugAI. It reads your imports, your function definitions,
and your call sites — and identifies whether the name was never defined, defined in wrong scope, or imported incorrectly.
Quick Reference
┌──────────────────────┬──────────────────────────────────────────┬──────────────────────────────────┐
│ Cause │ Symptom │ Fix │
├──────────────────────┼──────────────────────────────────────────┼──────────────────────────────────┤
│ Typo │ Name looks almost right │ Check spelling, case sensitivity │
├──────────────────────┼──────────────────────────────────────────┼──────────────────────────────────┤
│ Used before assigned │ Error on first reference │ Move reference after assignment │
├──────────────────────┼──────────────────────────────────────────┼──────────────────────────────────┤
│ Conditional scope │ Error only on some inputs │ Initialize before if block │
├──────────────────────┼──────────────────────────────────────────┼──────────────────────────────────┤
│ Function scope │ Error referencing another function's var │ Return and pass as argument │
├──────────────────────┼──────────────────────────────────────────┼──────────────────────────────────┤
│ Missing import │ Standard library or package name │ Add import at file top │
├──────────────────────┼──────────────────────────────────────────┼──────────────────────────────────┤
│ Try block scope │ Error after try/except │ Move usage inside try │
└──────────────────────┴──────────────────────────────────────────┴──────────────────────────────────┘
Fix NameErrors once and prevent them permanently: enable Pylance strict mode in VS Code ("python.analysis.typeCheckingMode": "strict"). It catches
undefined names before you run the code.
Debug faster starting today.
Free VS Code extension. 10 sessions/day. No credit card.