Quick answer
A variable was None when you used dot access on it (x.attr or x.method()). The fix is not at the crash line — it's wherever that variable became None. The usual culprit is a function with a missing return, or an API like re.match, dict.get, or list.sort() that returns None.
The exact error string
Traceback (most recent call last):
File "app.py", line 5, in <module>
print(user.name)
^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'
How to diagnose it in 30 seconds
The traceback's last line names the missing attribute ('name'); the line above shows the expression (user.name). So user is None. Now ask the only question that matters: where was user assigned, and why is it None there? Walk back to that assignment — that's where the fix goes, not the crash line.
Cause 1: function with a missing return
def find_user(uid):
for u in users:
if u.id == uid:
u # ❌ forgot `return` — function returns None
user = find_user(1)
print(user.name) # AttributeError: 'NoneType' ...
# ✅ actually return the value
def find_user(uid):
for u in users:
if u.id == uid:
return u
return None # explicit, and now you can check for it
Cause 2: an API that returns None
import re
m = re.match(r"\d+", "abc") # no match -> None
num = m.group() # ❌ 'NoneType' object has no attribute 'group'
# ✅ check the result before using it
m = re.match(r"\d+", "abc")
if m is not None:
num = m.group()
Cause 3: assigning the result of an in-place method
nums = [3, 1, 2]
nums = nums.sort() # ❌ sort() sorts in place and returns None
nums.append(4) # 'NoneType' object has no attribute 'append'
# ✅ don't reassign — sort/append/reverse mutate in place
nums = [3, 1, 2]
nums.sort()
nums.append(4)
Cause 4: a None from parsed JSON
import json
data = json.loads('{"user": null}') # JSON null -> Python None
name = data["user"].get("name") # ❌ user is None
# ✅ walk optional nesting safely
name = (data.get("user") or {}).get("name")
Need to see the shape of the payload first? Paste it into the JSON Formatter to confirm which fields are null or missing before you index into them.
Common sources of the None
| Call | Returns None when | Safe pattern |
|---|---|---|
re.match() / re.search() | no match | check if m: first |
dict.get(k) | key missing | dict.get(k, default) |
list.sort() / .append() | always (in-place) | don't assign the result |
function with no return | always | add an explicit return |
soup.find(...) / ORM .first() | nothing matched | guard for None |
Debugging checklist
- ✓ Read the attribute name and the expression on the line above — that variable is None
- ✓ Find where it's assigned; confirm that source can return None
- ✓ Function source? Add an explicit
returnon every path - ✓ In-place method (
sort/append/reverse)? Stop reassigning its result - ✓ From JSON/dict? Use
.get(k, default)or(x or {})chaining - ✓ Still need None as valid? Guard with
if x is not None:
Frequently Asked Questions
What does 'NoneType object has no attribute' mean?
A variable held None (Python's null) at the moment you accessed an attribute or called a method on it. None is of type NoneType, which has none of the attributes you expected, so Python raises AttributeError. The real bug is wherever that variable became None.
Why is my variable None when I expected an object?
The most common source is a function that fell off the end without an explicit return (so it returned None implicitly), or an API that returns None to signal "not found" — re.match, dict.get, list.append, BeautifulSoup .find, ORM .first(). Those return None, not the object you assumed.
Why does my function return None?
A Python function with no return statement (or a return with no value, or a return that only runs on some branches) yields None. A frequent mistake is calling an in-place method like list.sort() or list.append() and assigning its result — they mutate and return None.
How do I fix 'NoneType has no attribute'?
Trace back to where the variable is assigned and confirm it can't be None there. Then either fix the source (add a return, use the right API), guard with if x is not None before access, or short-circuit with x and x.attr / getattr(x, 'attr', default).
Why do I get this after parsing JSON?
JSON null becomes Python None, and data.get('key') returns None for a missing key. So data['user'].get('name') throws if 'user' is absent or null. Check for None at each level, or use data.get('user', {}).get('name') to walk optional nesting safely.
What is the difference between this and 'NoneType is not subscriptable'?
"has no attribute" is dot access on None (x.attr or x.method()). "is not subscriptable" is bracket access on None (x[0] or x['key']). Same root cause — the value is None — different operation. They often appear together when chaining off the same None.
Inspect the data that produced the None
If the None came from a JSON payload, format and explore it to see which fields are null or missing before you access them.