reference
3 min read
·
lesson 7 of 45 in Errors
AttributeError: 'NoneType' object has no attribute 'X'
1 · The lesson
readWhat this error means
You called a method or accessed an attribute on None. None is Python's "absence of a value" — it has none of the methods you'd expect on a string, list, dict, or custom object. Whatever you thought you had, you actually have None. The fix is to find out why it's None, not to add a try/except.
When you see it
python
Traceback (most recent call last): File "main.py", line 3, in <module> name = user.get("name").upper() AttributeError: 'NoneType' object has no attribute 'upper'
Why it happens
The classic trap: chaining a method onto something that can return None.
python
user = {"id": 1}
name = user.get("name").upper() # .get returns None — boomOther common sources:
re.match(...)/re.search(...)returnsNoneon no match.dict.get(key)returnsNonewhen the key is missing (and you didn't pass a default).- An ORM
.first()returnsNonewhen there's no row. - A function forgot to
return, so it implicitly returnedNone. - Chained
.find(...)calls on BeautifulSoup that didn't match.
How to fix it
Pass a default to dict.get:
python
name = user.get("name", "").upper() # default "" so .upper() always works
setup added so this can run · defines user
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) user = _AutoMock('user')
Guard with if x is not None when None is genuinely meaningful:
python
match = re.match(r"\d+", text) if match is not None: number = int(match.group())
setup added so this can run · defines text, re
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) text = _AutoMock('text') re = _AutoMock('re')
Use the walrus operator to test and reuse:
python
if (row := db.first()) is not None: print(row.name)
setup added so this can run · defines row, db
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) row = _AutoMock('row') db = _AutoMock('db')
Fix the upstream function — if a function should always return a string, give it a sensible fallback instead of letting it return None:
python
def display_name(user): return user.get("name") or "anonymous" # never returns None
When you'd actually see this in real code
- API response missing an optional field:
data.get("address").get("city")blows up whenaddressis absent. os.environ.get("DATABASE_URL").split("@")when the env var isn't set.- A BeautifulSoup scrape:
soup.find("div", class_="price").textwhen the div is missing on some pages. - A database
.first()returningNonebecause the row was just deleted.
Related errors
- TypeError: 'NoneType' object is not iterable — same root cause (forgot return, missing value) — different symptom.
- AttributeError: 'list' object has no attribute 'X' — wrong type, not missing value.
- AttributeError: module 'X' has no attribute 'Y'
See Also
- All Python errors — the full index, by type and by when it happens.
- Dictionaries (tutorial)
- Defensive coding cheat sheet
- Functions (tutorial)