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 value for "no value". It has none of the methods of a string, list, dict or custom object. The variable you used holds None, not the object you expected. The fix is to find out why it is None, not to add a try/except.
When you see it
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 most common mistake: calling a method directly on the result of something that can return None.
user = {"id": 1}
name = user.get("name").upper() # .get returns None, so this line crashesOther 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:
name = user.get("name", "").upper() # default "" so .upper() always works
setup added so this can run · re-runs 1 earlier block on this page first
# 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') # Earlier blocks on this page that this one builds on, re-run quietly first. _pm_earlier = [ 'user = {"id": 1}\nname = user.get("name").upper() # .get returns None, so this line crashes', ] def _pm_run_earlier(_srcs, _g): import sys as _s, io as _io, warnings as _w for _src in _srcs: _o, _e = _s.stdout, _s.stderr _s.stdout = _s.stderr = _io.StringIO() try: with _w.catch_warnings(): _w.simplefilter('ignore') exec(compile(_src, '<earlier block>', 'exec'), _g) except (Exception, SystemExit): pass finally: _s.stdout, _s.stderr = _o, _e if 'matplotlib.pyplot' in _s.modules: _s.modules['matplotlib.pyplot'].close('all') # their plots belong to their own blocks _pm_run_earlier(_pm_earlier, globals()) del _pm_earlier, _pm_run_earlier
Check with if x is not None when None is a normal, expected result:
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 the value and use it in one step:
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 function that returns None. If a function should always return a string, give it a fallback value instead of letting it return None:
def display_name(user): return user.get("name") or "anonymous" # never returns None
When you'd see this in real code
- An API response without an optional field:
data.get("address").get("city")fails whenaddressis missing. 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: the same root cause (a missing return, a missing value), but a different error.
- AttributeError: 'list' object has no attribute 'X': a wrong type, not a 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)
Found this useful? Share it with a friend who’s learning Python.