TypeError: ‘NoneType’ Object Is Not Subscriptable in Python — What It Means and How to Fix It

Hitting “TypeError: ‘NoneType’ object is not subscriptable” in Python? This guide explains exactly why it happens, the most common causes, and the right fixes — with real code examples you can use right now.

'NoneType' Object Is Not Subscriptable in Python


Few Python errors are as confusing on first sight as TypeError: 'NoneType' object is not subscriptable. You look at your code, you see what looks like a perfectly normal list or dictionary access, and yet Python fires back with this message. The frustrating part is that the variable in question often worked fine a few lines earlier.

This post walks through exactly what this error means, why it shows up in so many different situations, and how to fix it without just slapping a band-aid on top.


What Does “NoneType Object Is Not Subscriptable” Actually Mean?

Let’s decode the error message piece by piece.

Subscriptable means an object supports index or key access using square brackets. Lists, tuples, dictionaries, and strings are all subscriptable. You can do my_list[0] or my_dict["key"] without issue.

NoneType is Python’s built-in type for the value None. It represents the absence of a value — not zero, not an empty list, just nothing. And None does not support square bracket access.

So when Python says 'NoneType' object is not subscriptable, it means you have a variable that holds None, and somewhere in your code you tried to use it like a list or dictionary with brackets. Python doesn’t know what index or key you’re referring to because there’s no underlying data structure to look into.

A minimal example of the error:

python
my_list = None
print(my_list[0])
# TypeError: 'NoneType' object is not subscriptable

That’s the core of it. Now let’s look at where None sneaks in when you’re not expecting it.


The Most Common Causes

1. A Function Returns None When You Expected a Value

This is the single most frequent cause. Python functions that don’t have an explicit return statement — or that reach a code path without one — return None by default.

python
def get_user(user_id):
    if user_id == 1:
        return {"name": "Alice", "role": "admin"}
    # No return for other IDs — implicitly returns None

user = get_user(99)
print(user["name"])  # TypeError: 'NoneType' object is not subscriptable

The function looks like it returns a dictionary, and it does — for one specific case. For every other input, it returns None. If you call it with an unhandled ID and then try to access a key, you hit the error.

2. Assigning the Result of an In-Place List Method

This trips up a lot of Python beginners, and it’s a genuine gotcha. Methods like sort(), reverse(), and append() modify a list in place and return None. They do not return the modified list.

python
scores = [3, 1, 4, 1, 5, 9]
sorted_scores = scores.sort()
print(sorted_scores[0])  # TypeError: 'NoneType' object is not subscriptable

scores.sort() sorts the list and returns None. Assigning that to sorted_scores gives you a variable that holds None, not the sorted list. If you want a new sorted list, use the built-in sorted() function instead:

python
sorted_scores = sorted(scores)
print(sorted_scores[0])  # Works fine

3. An Uninitialized Variable

If you declare a variable with None as a placeholder and forget to assign a real value before using it, you’ll hit this error:

python
result = None
# ... some conditional logic that might not always assign result ...
print(result[0])  # TypeError if result was never assigned

This pattern often shows up in larger functions where the assignment is inside an if block, and the if condition didn’t trigger.

4. A Failed Data Fetch or Parse

When fetching data from an API, a database, or a file, it’s common to return None when something goes wrong:

python
import json

def parse_config(raw):
    try:
        return json.loads(raw)
    except json.JSONDecodeError:
        return None

config = parse_config("not valid json")
print(config["host"])  # TypeError: 'NoneType' object is not subscriptable

The parse fails silently, returns None, and the next line that tries to use the result crashes. This pattern is especially common in data pipelines — if you work with data at scale, you’ll see this type of silent failure regularly. Understanding how data flows through systems is something explored in depth in DataOps vs MLOps: Let’s Understand the Differences — the principles of validating data before processing apply just as much in Python scripts as in enterprise pipelines.

5. Regex Match That Returns None

The re module’s search() and match() functions return a match object when successful, and None when there’s no match. Accessing groups from a None result triggers the error:

python
import re

result = re.search(r'\d+', 'no numbers here')
print(result.group(0))  # AttributeError, but similar pattern
print(result[0])        # TypeError: 'NoneType' object is not subscriptable

Always check that a match was found before accessing it.


How to Fix TypeError: ‘NoneType’ Object Is Not Subscriptable

Fix 1: Check for None Before Accessing

The most direct fix is adding an explicit None check before you try to use the value:

python
user = get_user(99)

if user is not None:
    print(user["name"])
else:
    print("User not found")

Use is not None rather than just if user: because an empty dictionary {} is falsy but is not None, and you’d incorrectly skip it.

Fix 2: Provide a Default Value

When a function might return None, set a safe fallback using or:

python
user = get_user(99) or {}
print(user.get("name", "Unknown"))

Or with dict.get() you can handle missing keys gracefully without an extra check:

python
if user is not None:
    name = user.get("name", "Unknown")

Fix 3: Fix the Function to Always Return the Right Type

Rather than defending against None everywhere it could appear, fix the function that produces it. Make sure every code path returns a value of the expected type:

python
def get_user(user_id):
    if user_id == 1:
        return {"name": "Alice", "role": "admin"}
    return {}  # Return an empty dict instead of None

This is cleaner and puts the logic where it belongs.

Fix 4: Use sorted() Instead of sort()

If the None comes from an in-place list method, switch to the functional equivalent:

python
# Instead of:
sorted_scores = scores.sort()

# Use:
sorted_scores = sorted(scores)

The same principle applies to other in-place methods. When you need to chain or assign, use the function form that returns a new object.

Fix 5: Add a Guard at the Point of the Regex Match

python
import re

result = re.search(r'\d+', text)
if result:
    print(result[0])
else:
    print("No match found")

Debugging When You Can’t Spot It

If the error is buried inside a larger function and you can’t immediately see where None is coming from, add a print statement or use a debugger right before the line that fails:

python
print(type(user), user)  # Check what you actually have before accessing it
print(user["name"])

You can also use Python’s assert statement during development to catch the issue early:

python
assert user is not None, f"Expected a user dict, got None for user_id={user_id}"

This turns a confusing TypeError into a clear, human-readable AssertionError with context. In production code, replace asserts with proper exception handling.

Understanding where silent failures can enter your data flow is critical in any serious Python project. The same discipline applies whether you’re parsing JSON, working with APIs, or building ML pipelines. How data gets processed, validated, and passed between systems matters — as covered in How Can Telematics Data Improve Freight Transportation, where real-time data quality directly affects system reliability.


A Note on Type Hints

Python’s type hints can prevent this class of error before it ever reaches runtime. If you annotate your functions with return types, tools like mypy will flag potential None-related problems at development time:

python
from typing import Optional

def get_user(user_id: int) -> Optional[dict]:
    if user_id == 1:
        return {"name": "Alice"}
    return None

With Optional[dict] in the signature, any caller that doesn’t check for None before indexing will get a warning from your linter. It’s a small habit that prevents a lot of runtime surprises.

For developers stepping up from scripting to building larger Python applications, adopting type hints alongside better data validation practices is one of the highest-leverage improvements you can make. The broader discipline of data quality and testing is something that scales from small Python functions all the way to enterprise data platforms — you can explore how these principles apply at scale in Top Software Testing Companies USA.


Key Takeaways

The TypeError: 'NoneType' object is not subscriptable error has one root cause: you tried to use square-bracket indexing on a variable that holds None. The tricky part is figuring out how None got there.

Here’s what to check:

  • Does every branch of your function have an explicit return statement?
  • Are you assigning the result of sort(), append(), or reverse() to a variable? Use sorted() instead.
  • Is your data fetch, API call, or file parse returning None on failure without you noticing?
  • Are you checking regex match results before accessing groups?

The fix is almost always one of three things: check for None before accessing, fix the function to return the right type, or use the non-mutating equivalent of an in-place method. Pick the fix that addresses the root cause, not just the symptom.