Fix: Python AttributeError: 'NoneType' object has no attribute
Quick Answer
How to fix Python AttributeError NoneType object has no attribute caused by functions returning None, method chaining, failed lookups, uninitialized variables, and missing return statements.
The Error
You run your Python script and get:
Traceback (most recent call last):
File "app.py", line 12, in <module>
print(result.name)
^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'Or variations like:
AttributeError: 'NoneType' object has no attribute 'append'AttributeError: 'NoneType' object has no attribute 'split'AttributeError: 'NoneType' object has no attribute 'get'The attribute name changes, but the pattern is the same: you tried to access a property or call a method on something that is None. Python does not know what .name, .append(), or .split() means on None because None has no attributes.
Why This Happens
In Python, None is a special object that represents the absence of a value. When a variable holds None and you try to access an attribute on it, Python raises AttributeError.
The critical question is: why is the variable None in the first place? Here are the most common causes:
- A function returned
Noneimplicitly. Python functions that don’t have areturnstatement (or have a barereturn) returnNoneby default. - A list method returned
None. Methods like.sort(),.append(),.reverse(), and.extend()modify the list in place and returnNone. - A dictionary lookup returned
None.dict.get()returnsNonewhen the key is not found (unless you provide a default). - A failed search returned
None.re.match(),re.search(), andlist.find()equivalents returnNonewhen there is no match. - A variable was never assigned. You declared a variable but never gave it a value, or a conditional branch skipped the assignment.
- Method chaining on a mutating method. Calling
.sort().reverse()fails because.sort()returnsNone.
Fix 1: Check Functions That Return None Implicitly
The most common cause. A function without an explicit return statement returns None:
def find_user(users, name):
for user in users:
if user["name"] == name:
return user
# No return here — returns None if user not found
result = find_user(users, "Alice")
print(result.name) # AttributeError if Alice is not in the listFix: Always handle the case where the function returns None:
result = find_user(users, "Alice")
if result is not None:
print(result["name"])
else:
print("User not found")Or make the function raise an exception instead of returning None:
def find_user(users, name):
for user in users:
if user["name"] == name:
return user
raise ValueError(f"User '{name}' not found")Pro Tip: Use type hints to make
Nonereturns explicit.def find_user(...) -> dict | None:tells both the developer and tools like mypy that the function can returnNone. This catches the error before you even run the code.
Fix 2: Don’t Chain Methods That Return None
List methods that modify in place return None. Chaining them is a classic Python trap:
# WRONG — .sort() returns None
sorted_names = names.sort()
print(sorted_names.reverse()) # AttributeError: 'NoneType' has no attribute 'reverse'# WRONG — .append() returns None
result = my_list.append("item")
print(result.count("item")) # AttributeErrorFix: Call mutating methods on separate lines:
names.sort()
names.reverse()
print(names)Or use the non-mutating alternatives that return a new object:
sorted_names = sorted(names) # Returns new list
reversed_names = list(reversed(names)) # Returns new listMethods that modify in place and return None:
| Method | Returns | Alternative |
|---|---|---|
list.sort() | None | sorted(list) |
list.append(x) | None | list + [x] |
list.extend(x) | None | list + x |
list.reverse() | None | list[::-1] or reversed(list) |
list.insert(i, x) | None | — |
dict.update(x) | None | {**dict, **x} |
set.add(x) | None | — |
This is closely related to the NoneType not subscriptable error, which occurs when you try to index None with [] instead of accessing an attribute with ..
Fix 3: Handle dict.get() and Missing Keys
dict.get() returns None when the key doesn’t exist:
config = {"host": "localhost", "port": 3306}
db_name = config.get("database")
print(db_name.upper()) # AttributeError: 'NoneType' has no attribute 'upper'Fix: Provide a default value:
db_name = config.get("database", "mydb")
print(db_name.upper()) # Works — defaults to "mydb"Or check before using:
db_name = config.get("database")
if db_name:
print(db_name.upper())If the key must exist and its absence is an error, use direct access:
db_name = config["database"] # Raises KeyError if missing — better than a silent NoneFix 4: Handle None from re.match() and re.search()
Regex functions return None when there is no match:
import re
text = "no numbers here"
match = re.search(r'\d+', text)
print(match.group()) # AttributeError: 'NoneType' has no attribute 'group'Fix: Check the match before accessing groups:
match = re.search(r'\d+', text)
if match:
print(match.group())
else:
print("No match found")Or use the walrus operator (Python 3.8+):
if match := re.search(r'\d+', text):
print(match.group())Fix 5: Fix Uninitialized Variables and Conditional Assignments
A variable might be None because a conditional branch never assigned it:
def get_discount(user_type):
if user_type == "premium":
discount = 0.2
elif user_type == "member":
discount = 0.1
# No else — discount is undefined for other types
return discount # UnboundLocalError or None if initialized earlierFix: Always provide a default value:
def get_discount(user_type):
discount = 0.0 # Default
if user_type == "premium":
discount = 0.2
elif user_type == "member":
discount = 0.1
return discountFix 6: Fix Class init and Missing Returns
If __init__ accidentally returns something, or a class method forgets to return, you get None:
class UserService:
def get_user(self, user_id):
user = self.db.query(user_id)
# Forgot to return user!
service = UserService()
user = service.get_user(123)
print(user.name) # AttributeError: 'NoneType' has no attribute 'name'Fix: Add the return statement:
def get_user(self, user_id):
user = self.db.query(user_id)
return user # Don't forget this!Common Mistake: In Python,
__init__must not return a value. If you tryreturn somethingin__init__, Python raisesTypeError. But forgettingreturnin other methods is the most common cause of this error in class-based code.
Fix 7: Handle API and Database Responses
External data sources can return None unexpectedly:
import requests
response = requests.get("https://api.example.com/user/123")
data = response.json()
# The API might return {"user": null}
user = data.get("user")
print(user["name"]) # AttributeError if user is NoneFix: Validate the response before using it:
user = data.get("user")
if user is None:
raise ValueError("API returned no user data")
print(user["name"])For database ORMs:
# SQLAlchemy
user = session.query(User).filter_by(id=123).first() # Returns None if not found
if user is None:
raise ValueError("User not found")
print(user.name)Fix 8: Debug with print() and type()
When you cannot figure out why a variable is None, add debug prints:
result = some_function()
print(f"result = {result}")
print(f"type = {type(result)}")
# If result is None, trace back to some_functionCheck every step in a chain:
a = step_one()
print(f"after step_one: {a} (type: {type(a)})")
b = a.step_two()
print(f"after step_two: {b} (type: {type(b)})")
c = b.step_three() # If b is None, this is where it crashesUse Python’s traceback module for more detail:
import traceback
try:
result.name
except AttributeError:
traceback.print_exc()
print(f"result was: {result!r}")If your debugging reveals an import issue rather than a None value, check fixing ModuleNotFoundError or circular import errors.
Fix 9: Use Type Hints and mypy
Type hints catch None attribute access at development time:
from typing import Optional
def find_user(name: str) -> Optional[dict]:
# Returns dict or None
...
result = find_user("Alice")
print(result.name) # mypy flags this: Item "None" of "Optional[dict]" has no attribute "name"Run mypy to catch these before runtime:
pip install mypy
mypy your_script.pyModern Python (3.10+) uses dict | None instead of Optional[dict]:
def find_user(name: str) -> dict | None:
...Still Not Working?
If you have checked all the fixes above and still get this error:
Check for monkey-patching. Something might be overwriting a variable or attribute with None at runtime. Search your codebase for assignments to the variable in question.
Check for thread safety. In multithreaded code, one thread might set a value to None while another thread tries to access its attributes. Use locks or thread-safe data structures.
Check decorator return values. A decorator that forgets to return the wrapped function effectively replaces the function with None:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("before")
func(*args, **kwargs)
# Missing: return func(*args, **kwargs)
# Missing: return wrapper
@my_decorator
def my_function():
return "hello"
my_function() # TypeError or AttributeError — my_function is NoneFix both return statements in the decorator.
Check for property setters. A @property that returns None implicitly causes this error when you access nested attributes on the property value. This behaves the same as TypeError: cannot read properties of undefined in JavaScript — both errors stem from accessing attributes on an empty value.
Check for circular imports causing partial initialization. If module A imports from module B, and module B imports from module A, some variables in the modules may be None during initialization. See fixing Python circular imports.
Use assertions during development. Add assert statements to catch None values early:
result = find_user("Alice")
assert result is not None, "find_user returned None — user not found"
print(result.name)Assertions are removed when Python runs with -O (optimize) flag, so they don’t affect production performance.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: AWS Lambda Unable to import module / Runtime.ImportModuleError
How to fix the AWS Lambda Runtime.ImportModuleError and Unable to import module error caused by wrong handler paths, missing dependencies, layer issues, and packaging problems.
Fix: Python TypeError: unhashable type: 'list'
Learn why Python raises TypeError unhashable type list, dict, or set and how to fix it when using dictionary keys, sets, groupby, dataclasses, and custom classes.
Fix: Django Forbidden (403) CSRF verification failed
How to fix Django 403 CSRF verification failed error caused by missing CSRF tokens, AJAX requests, cross-origin issues, HTTPS misconfig, and session problems.
Fix: FastAPI 422 Unprocessable Entity (validation error)
How to fix FastAPI 422 Unprocessable Entity error caused by wrong request body format, missing fields, type mismatches, query parameter errors, and Pydantic validation.