Quick answer
You used bracket indexing — x[0] or x["key"] — on a value that was None. None isn't a list, dict, or string, so it can't be subscripted. Find where the variable became None (a missing return, or a None-returning call) and fix it there, or guard the access.
The exact error string
Traceback (most recent call last):
File "app.py", line 4, in <module>
print(config["host"])
^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable
How to diagnose it in 30 seconds
The traceback line shows the subscript expression (config["host"]), so the thing before the brackets — config — is None. Don't patch the crash line. Ask: where did config get assigned, and what returned None there? That assignment is the bug.
Cause 1: function returned None
def load_config(path):
if os.path.exists(path):
return json.load(open(path))
# ❌ no return on the else path -> None
config = load_config("missing.json")
print(config["host"]) # TypeError: 'NoneType' object is not subscriptable
# ✅ return a sensible default
def load_config(path):
if os.path.exists(path):
return json.load(open(path))
return {}
Cause 2: assigning an in-place method's result
rows = [3, 1, 2]
rows = rows.sort() # ❌ sort() returns None
first = rows[0] # 'NoneType' object is not subscriptable
# ✅ sort in place, don't reassign
rows = [3, 1, 2]
rows.sort()
first = rows[0]
Cause 3: indexing a None from parsed JSON
import json
data = json.loads('{"user": null}') # JSON null -> Python None
name = data["user"]["name"] # ❌ data["user"] is None
# ✅ check the level, or default it
user = data.get("user") or {}
name = user.get("name")
Unsure which fields are null? Drop the payload into the JSON Formatter to see the structure before you index into it.
Cause 4: a query/lookup that found nothing
row = cursor.fetchone() # no rows -> None
user_id = row[0] # ❌ 'NoneType' object is not subscriptable
# ✅ guard for the empty result
row = cursor.fetchone()
if row is not None:
user_id = row[0]
Common sources of the None
| Source | Returns None when | Safe pattern |
|---|---|---|
function with no return | some/all paths | return a default ({}/[]) |
list.sort()/.append() | always (in-place) | don't reassign the result |
JSON null field | field is null/absent | (x or {})[...] / .get |
cursor.fetchone() | no matching row | if row is not None: |
dict.get(k) | key missing | dict.get(k, {}) |
Debugging checklist
- ✓ Read the subscript expression — the value before
[ ]is None - ✓ Trace it to its assignment; confirm what can return None there
- ✓ Function source? Add a
return(default collection) on every path - ✓ In-place method? Stop reassigning
sort/append/reverse - ✓ JSON/DB? Default with
x or {}/x or [], or guard withis not None
Frequently Asked Questions
What does 'NoneType object is not subscriptable' mean?
You used square-bracket indexing — x[0] or x['key'] — on a value that was None. Subscripting (the [ ] operator) is only defined for sequences and mappings like list, str, dict, and tuple; None supports none of that, so Python raises TypeError.
Why is the value None instead of a list or dict?
Usually a function returned None (a missing or conditional return), or a None-returning API was used as if it returned a collection — json.load on the wrong thing, a dict.get with no default, list.sort() assigned to a variable, or a DB query that found no row.
How do I fix 'NoneType is not subscriptable'?
Trace the variable back to its assignment and confirm it can't be None. Fix the real source (add a return, pass a default), or guard the access: if x is not None: x[0], or x = func() or [] to fall back to an empty collection.
Why does this happen with json.loads or a JSON field?
JSON null decodes to Python None, so data['user']['name'] throws if 'user' is null. Also, assigning the result of json.dump (which returns None) by mistake and then indexing it triggers this. Inspect the JSON structure and check each level for None before indexing.
Why did list.sort() or .append() cause this?
In-place methods return None. If you write data = data.sort() or rows = rows.append(r), data/rows become None, and the next data[0] raises "not subscriptable". Call the method without reassigning its result.
What's the difference between 'not subscriptable' and 'has no attribute'?
"not subscriptable" is bracket access on None (x[0], x['key']). "has no attribute" is dot access on None (x.attr, x.method()). Both mean the value is None; the operation differs. The fix is the same: eliminate or guard the None.
Inspect the JSON that produced the None
If the None came from a parsed payload, format it to see which fields are null or missing before you index into them.