AttributeError: 'NoneType' object has no attribute 'x' means the value before the dot is None, so it has no .x to read or call. The None usually comes from an in-place method such as list.sort() or list.append(), a function that does not return anything, or a lookup that found nothing, such as re.match(), dict.get() or ElementTree's find(). Find where the variable became None, then either return a real value or check if value is None before using it.
The attribute name in quotes tells you what you tried to use, but not where the None came from. The caret markers in Python 3.11 and later help, because they underline the expression that produced None.
Every traceback below comes from Python 3.13.5 on my machine. Python 3.10 and 3.14.8 printed the same message for the main example.
In this guide:
- Cause 1: Assigning the result of sort() or append()
- Cause 2: A function that does not return on every path
- Cause 3: re.match() found nothing
- Cause 4: dict.get() for a missing key
- Cause 5: Storing the result of print()
- Cause 6: find() in XML or HTML parsers
- Cause 7: Chaining a method that returns None
- Cause 8: The end of a linked list or an optional attribute
- Cause 9: null in JSON data
- Cause 10: A missing environment variable
- How to find where the None came from
- Quick fix table
- Frequently asked questions
Cause 1: Assigning the result of sort() or append()
nums = [3, 1, 2]
nums = nums.sort()
print(nums.append(4))
Traceback (most recent call last):
File "c01_sort.py", line 3, in <module>
print(nums.append(4))
^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'append'
List methods that change the list in place, such as sort(), append(), extend() and reverse(), return None. Writing nums = nums.sort() throws the list away. Call the method on its own, or use sorted() when you want a new list:
nums = [3, 1, 2]
nums.sort()
nums.append(4)
print(nums)
print(sorted([3, 1, 2]))
[1, 2, 3, 4]
[1, 2, 3]
The list methods documentation notes that sort() modifies the list in place and returns None on purpose, to remind you that no new list was created.
Cause 2: A function that does not return on every path
def load_user(user_id):
users = {1: {"name": "Ana"}}
if user_id in users:
user = users[user_id]
user = load_user(1)
print(user.get("name"))
Traceback (most recent call last):
File "c02_no_return.py", line 7, in <module>
print(user.get("name"))
^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'
load_user() found the user and stored it in a local variable, but never returned it, so the caller got None. A function without a return statement, or one that reaches the end on some path, returns None. Return the value and handle the not-found case explicitly:
def load_user(user_id):
users = {1: {"name": "Ana"}}
return users.get(user_id)
for uid in (1, 2):
user = load_user(uid)
if user is None:
print(uid, "-> not found")
else:
print(uid, "->", user.get("name"))
1 -> Ana
2 -> not found
The same missing-return bug causes 'NoneType' object is not subscriptable when you use square brackets instead of a dot.
Cause 3: re.match() found nothing
import re
m = re.match(r"(\d+)-(\d+)", "order 12-34")
print(m.group(1))
Traceback (most recent call last):
File "c03_re_match.py", line 3, in <module>
print(m.group(1))
^^^^^^^
AttributeError: 'NoneType' object has no attribute 'group'
re.match() only matches at the start of the string, and the string starts with order, so it returned None. Use re.search() to find the pattern anywhere, and always check the match before calling .group():
import re
text = "order 12-34"
print(re.match(r"(\d+)-(\d+)", text))
m = re.search(r"(\d+)-(\d+)", text)
if m:
print(m.group(1), m.group(2))
None
12 34
The re module documentation explains the difference between match(), search() and fullmatch(), and that each returns None when there is no match.
Cause 4: dict.get() for a missing key
config = {"db": {"host": "localhost"}}
print(config.get("cache").get("ttl"))
Traceback (most recent call last):
File "c04_dict_get.py", line 2, in <module>
print(config.get("cache").get("ttl"))
^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'
dict.get() returns None for a missing key instead of raising KeyError, so the error moves to the next dot. Pass a default of the right type:
config = {"db": {"host": "localhost"}}
print(config.get("cache", {}).get("ttl", 300))
payload = {"user": None}
print((payload.get("user") or {}).get("name", "guest"))
300
guest
The second line also shows the fix for cause 9. If you prefer a loud failure for missing keys, use square brackets; my KeyError guide covers that side.
Cause 5: Storing the result of print()
text = " Hello "
result = print(text.strip())
result.lower()
Hello
Traceback (most recent call last):
File "c05_chain.py", line 3, in <module>
result.lower()
^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'lower'
print() writes to the screen and returns None. Store the value first, then print it: result = text.strip() followed by print(result). The same happens with any function that only has side effects, such as random.shuffle(). For quick checks on text and data, my free tools page has browser-based helpers.
Cause 6: find() in XML or HTML parsers
import xml.etree.ElementTree as ET
root = ET.fromstring("<user><name>Ana</name></user>")
print(root.find("email").text)
Traceback (most recent call last):
File "c06_find.py", line 3, in <module>
print(root.find("email").text)
^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'text'
ElementTree's find() returns None when no element matches, and so do find() methods in many HTML parsing libraries. Check the result, or use findtext() with a default:
import xml.etree.ElementTree as ET
root = ET.fromstring("<user><name>Ana</name></user>")
if (email := root.find("email")) is not None:
print(email.text)
else:
print("no email element")
print(root.findtext("email", default="n/a"))
no email element
n/a
Note the is not None check: an element with no children is falsy, so if email: could skip a real element. The ElementTree documentation warns about exactly this.
Cause 7: Chaining a method that returns None
class Cart:
def __init__(self):
self.items = []
def add(self, item):
self.items.append(item)
cart = Cart().add("apple")
cart.add("pear")
Traceback (most recent call last):
File "c07_init_return.py", line 9, in <module>
cart.add("pear")
^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'add'
add() changes the cart but returns nothing, so cart is None. Either call the methods on separate lines, or make the method return self if you want chaining:
class Cart:
def __init__(self):
self.items = []
def add(self, item):
self.items.append(item)
return self
cart = Cart().add("apple").add("pear")
print(cart.items)
['apple', 'pear']
Cause 8: The end of a linked list or an optional attribute
class Node:
def __init__(self, value, next=None):
self.value, self.next = value, next
head = Node(1, Node(2))
print(head.next.value)
print(head.next.next.value)
2
Traceback (most recent call last):
File "c08_optional_attr.py", line 7, in <module>
print(head.next.next.value)
^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'value'
The second node's next is None, the normal end of the list. Any attribute that can be None by design, such as a parent, a next node or an optional profile, needs a check. Loop until None, or use getattr() with a default:
class Node:
def __init__(self, value, next=None):
self.value, self.next = value, next
node = Node(1, Node(2))
while node is not None:
print(node.value)
node = node.next
third = Node(1, Node(2)).next.next
print(getattr(third, "value", "no third node"))
1
2
no third node
Cause 9: null in JSON data
import json
payload = json.loads('{"user": null}')
print(payload["user"].get("name"))
Traceback (most recent call last):
File "c10_api.py", line 3, in <module>
print(payload["user"].get("name"))
^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'
JSON null becomes Python None. APIs often send null for missing nested objects, so code that worked in testing fails in production. The (payload.get("user") or {}) pattern from cause 4 handles both a missing key and a null value. If the response is not JSON at all, you get a different error, covered in my guide to Unexpected token is not valid JSON.
Cause 10: A missing environment variable
import os
paths = os.environ.get("MYAPP_PLUGIN_PATHS").split(":")
Traceback (most recent call last):
File "c09_environ.py", line 2, in <module>
paths = os.environ.get("MYAPP_PLUGIN_PATHS").split(":")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'split'
os.environ.get() returns None when the variable is not set, which is common in a new terminal, a cron job or a container. Give it a default, and filter out the empty string if you split it:
import os
paths = os.environ.get("MYAPP_PLUGIN_PATHS", "").split(":")
print(paths)
os.environ["MYAPP_PLUGIN_PATHS"] = "/opt/a:/opt/b"
print(os.environ.get("MYAPP_PLUGIN_PATHS", "").split(":"))
print([p for p in "".split(":") if p])
['']
['/opt/a', '/opt/b']
[]
The os module documentation describes os.environ and os.getenv(), which also accepts a default.
How to find where the None came from
- Read the caret line. It underlines the expression that was
None. - Find where that variable was last assigned. Look for
= something.sort(), = print(...) or a function call. - Open that function and check every path ends with a
return. - If the value can legitimately be missing, add
if value is None: right after you get it, not three lines later. - Use type hints such as
-> User | None so editors and type checkers warn you before you run the code.
Why is None and not == None? My post on Python is vs == explains.
Quick fix table
| Source of None | Example | Fix |
|---|
| In-place list method | nums = nums.sort() | Call nums.sort() on its own line, or use sorted() |
| Function without return | user = load_user(1) | Return a value on every path |
| re.match / re.search found nothing | m.group(1) | Check if m: first |
| dict.get() for a missing key | config.get("cache").get("ttl") | .get("cache", {}) |
| print() result | result = print(x) | Store the value, not the print |
| ElementTree find() | root.find("email").text | findtext() or a None check |
| Method that returns None | Cart().add("apple").add(...) | Return self for chaining |
| Optional attribute or end of a linked list | head.next.next.value | Loop while node is not None |
| JSON null | payload["user"].get("name") | (payload.get("user") or {}) |
| Missing environment variable | os.environ.get("X").split(":") | Pass a default to get() |
If you hit 'str' object has no attribute or 'list' object has no attribute instead, the cause is a different type than you expected, not None, but the debugging steps are the same.
Frequently asked questions
What does 'NoneType' object has no attribute mean?
The value before the dot is None, so it has no attributes or methods. Usually a function returned None or a lookup found nothing.
Why does list.sort() return None?
sort() changes the list in place and returns None on purpose. Call nums.sort() on its own line, or use sorted(nums) to get a new sorted list.
Why does my function return None?
A function returns None when it has no return statement or when a path through it ends without one. Add a return for every path.
How do I fix 'NoneType' object has no attribute 'group'?
re.match or re.search found no match and returned None. Check if m: before calling m.group(), and use re.search if the pattern is not at the start of the string.
How do I avoid this error with dict.get?
Pass a default of the right type, such as config.get("cache", {}), or use (data.get("key") or {}) when the value can also be None.
Should I just wrap the code in try/except AttributeError?
Usually not. It can hide real bugs. Check for None where the value is created, and handle the missing case on purpose.
Can type hints prevent NoneType errors?
They help. Annotating a return type as User | None makes type checkers such as mypy warn when you use the result without a None check.
Last checked: 9 November 2026. Figures, settings and guidance can change, so confirm anything important with the sources linked above.