Sythra

Article

TypeError: 'NoneType' object is not subscriptable — the debug recipe

This error means a function handed you None and you tried to index it. Learn the three functions that return None most often and the two-line guard that fixes them.

vaibhavkothari· Aug 26, 2026· 5 min readBeginner
ShareXLinkedIn
TypeError: 'NoneType' object is not subscriptable — the debug recipe cover

TypeError: 'NoneType' object is not subscriptable sounds cryptic. It says something simple:

You used square brackets on None, and None has nothing inside it.

NonePython's word for "no value at all" is what a function returns when it has nothing useful to give back. None[0], None["name"], and None[1:3] are all meaningless, so Python stops.

The real bug is never on the line that crashed. It is wherever None was created. This guide shows you how to find that spot in about a minute.

The shape of the bug

import cv2

image = cv2.imread("photo.jpg")   # <- the real bug lives here
print(image[0])                   # <- but the crash happens here

cv2.imread returns None when it cannot read the file. It does not raise an error and it does not warn you. The program keeps going until something tries to index the result.

Step 1 — Find which variable is None

Print the value and the type right before the failing line:

print("value:", image)
print("type:", type(image))

If you see value: None and type: <class 'NoneType'>, you have found the guilty variable. Now walk upward to the line that assigned it.

Step 2 — Check the usual suspects

Four calls produce None far more often than anything else:

CallReturns None whenFix
cv2.imread(path)File missing, wrong path, or unsupported formatCheck the path exists before reading
re.match() / re.search()The pattern did not matchTest the result before using .group()
dict.get(key)The key is absentPass a default: d.get(k, {})
A function of your ownSome branch has no returnReturn a value on every path

That last one catches almost everyone at least once:

# Broken — nothing is returned when the list is empty
def first_item(items):
    if items:
        return items[0]

result = first_item([])
print(result[0])          # TypeError: 'NoneType' object is not subscriptable

Python inserts an invisible return None at the end of any function that falls off the bottom. Make the empty case explicit:

# Fixed
def first_item(items):
    if items:
        return items[0]
    return ""             # a real value, every time

Step 3 — Fix the OpenCV version properly

This is the number one source of the error for anyone learning computer vision. Do not just check for None; check the path and say why it failed:

from pathlib import Path
import cv2

path = Path("photo.jpg")

if not path.exists():
    raise FileNotFoundError(f"No such file: {path.resolve()}")

image = cv2.imread(str(path))

if image is None:
    raise ValueError(f"OpenCV could not decode: {path.resolve()}")

print("Loaded:", image.shape)

path.resolve() prints the full absolute path, which instantly reveals the usual culprit: your script runs from a different folder than you think, so "photo.jpg" points somewhere unexpected.

The same trap exists for video:

cap = cv2.VideoCapture(0)

if not cap.isOpened():
    raise RuntimeError("Camera did not open. Is another app using it?")

ok, frame = cap.read()
if not ok or frame is None:
    raise RuntimeError("Camera opened but returned no frame.")

We use exactly this guard in the virtual mouse project, because a webcam that silently returns None is a miserable thing to debug.

Step 4 — Guard regex results

re.search returns None on no match, and None.group() fails the same way:

import re

match = re.search(r"(\d{4})", "no digits here")

if match is None:
    print("No year found")
else:
    print("Year:", match.group(1))

The walrus operator makes this tidier in modern Python:

if (match := re.search(r"(\d{4})", text)) is not None:
    print("Year:", match.group(1))

Step 5 — Use safe defaults for dictionaries

Chained .get() calls are the classic source of this error in API code:

# Broken — 'address' may not exist
city = data.get("address")["city"]

# Fixed — an empty dict is still subscriptable
city = data.get("address", {}).get("city", "unknown")

The trick: give .get() a default of the same shape as the real value. A missing dict becomes {}, a missing list becomes []. The next operation then works instead of exploding.

Sibling errors you will meet

ErrorMeaning
'NoneType' object is not iterableYou looped over None
'NoneType' object has no attribute 'x'You used a dot on None
'NoneType' object is not callableYou called None()

All four have the same cure: find where None was born and handle that case.

The habit that prevents all of it

Check for None immediately after the call that could produce it — not three lines later, not in the function that uses the value. Fail loudly, with the path or key in the message. Debugging a clear error takes seconds; debugging a NoneType crash forty lines downstream takes an evening.

FAQ

What does 'NoneType' object is not subscriptable mean?

It means you used square brackets on a variable holding None. Because None contains no items, indexing, slicing, and key lookup are all invalid.

Why does cv2.imread return None?

The file path is wrong relative to where the script runs, the file is missing, or the format cannot be decoded. Print Path(p).resolve() to see the absolute path OpenCV actually tried.

How do I check for None in Python?

Use if value is None:, not ==. The is operator compares identity, which is the correct and fastest check for None.

Why does my function return None when I did not write return None?

Python adds an implicit return None whenever execution reaches the end of a function without hitting a return. An if with no matching else is the most common cause.

What is the difference between not subscriptable and not iterable?

Not subscriptable means you used [] on None. Not iterable means you tried to loop over None with a for statement. Both point back to the same missing value.

Next reading on Sythra Articles

Keep reading

Related articles

Newsletter

Get new articles

Free essays on learning, Python, and ML — no account required. We’ll only email when there’s something worth reading.