---
title: "TypeError: 'NoneType' object is not subscriptable — the debug recipe"
description: "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."
url: https://articles.sythra.ai/articles/nonetype-not-subscriptable-fix
slug: nonetype-not-subscriptable-fix
author: "vaibhavkothari"
author_url: https://articles.sythra.ai/writers/vaibhavkothari
date_published: 2026-08-26T08:26:25.097Z
date_modified: 2026-08-29T10:29:25.265Z
topics: ["Python", "Errors", "Opencv"]
reading_time_minutes: 5
publisher: "Sythra"
publisher_url: https://sythra.ai
access: free
language: en
---

# 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.

Source: https://articles.sythra.ai/articles/nonetype-not-subscriptable-fix · Author: vaibhavkothari · Published: 2026-08-26 · Reading time: 5 min · Topics: Python, Errors, Opencv

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

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

None 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

```python
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:

```python
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:

| Call | Returns None when | Fix |
|---|---|---|
| `cv2.imread(path)` | File missing, wrong path, or unsupported format | Check the path exists before reading |
| `re.match()` / `re.search()` | The pattern did not match | Test the result before using `.group()` |
| `dict.get(key)` | The key is absent | Pass a default: `d.get(k, {})` |
| A function of your own | Some branch has no `return` | Return a value on **every** path |

That last one catches almost everyone at least once:

```python
# 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:

```python
# 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:

```python
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:

```python
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](https://articles.sythra.ai/articles/virtual-mouse-opencv-mediapipe), 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:

```python
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:

```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:

```python
# 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

| Error | Meaning |
|---|---|
| `'NoneType' object is not iterable` | You looped over `None` |
| `'NoneType' object has no attribute 'x'` | You used a dot on `None` |
| `'NoneType' object is not callable` | You 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.

```remember
# Remember this
The error means -> a function returned `None` and you indexed it
`cv2.imread` -> returns `None` for a bad path, it does not raise
`re.search` -> returns `None` when there is no match
---
Do not fix the line that crashed. Fix the line that produced the `None`.
```


## 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

- [Build a virtual mouse with OpenCV and MediaPipe](https://articles.sythra.ai/articles/virtual-mouse-opencv-mediapipe)
- [ModuleNotFoundError: No module named 'cv2'](https://articles.sythra.ai/articles/no-module-named-cv2-fix)
- [ValueError: could not convert string to float](https://articles.sythra.ai/articles/could-not-convert-string-to-float-fix)

## Glossary (terms defined in this article)
- **None** (basic) — Python's word for "no value at all"
