Skip to content
Happy Programming Guide
Start learning
Python

Fixing “TypeError: object is not subscriptable” in Python

You used square brackets on something that does not support them: an int, a None, a function, a method you forgot to call. How the message names the type, and the fix for each.

A laptop computer on a table

TypeError: 'int' object is not subscriptable means you wrote something[...] and something was an integer, which has no items to index. The type in the quotes is the clue: it tells you what the value actually was, and that is nearly always not what you thought. The five common types that appear there each point to a specific mistake.

What subscriptable means#

Square brackets after a value — value[0], value["key"], value[1:3] — ask it for an item. Lists, tuples, strings, dictionaries and most containers support that. Numbers, None, functions and classes do not. The error says which unsupported type you used, so read it:

Output
TypeError: 'NoneType' object is not subscriptable
TypeError: 'int' object is not subscriptable
TypeError: 'builtin_function_or_method' object is not subscriptable
TypeError: 'type' object is not subscriptable

‘NoneType’: something returned None#

The most common case. A function that was expected to return a list or dictionary returned nothing, and you indexed the nothing.

Python
def load_config():
    config = {"debug": True}
    # forgot to return config

settings = load_config()
settings["debug"]                   # TypeError: 'NoneType' object is not subscriptable

Two other reliable sources of an unexpected None:

Python
names = ["b", "a"]
result = names.sort()               # sort() sorts in place and returns None
result[0]                           # TypeError

match = re.search(r"\d+", "no digits here")
match[0]                            # TypeError - search returned None, nothing matched

Methods that change an object in place — sort, append, reverse, update — return None. Use sorted(names) when you want a value back. For searches and lookups that can fail, check for None before indexing.

‘int’ or ‘float’: you indexed a number#

Python
for i in len(items):                # len returns an int; you cannot loop over it...
    ...
total = 5
total[0]                            # ...and you cannot index it either

Usually this means a name was reused. A variable that held a list earlier now holds a number:

Python
scores = [70, 85, 90]
scores = sum(scores)                # scores is now 245
scores[0]                           # TypeError: 'int' object is not subscriptable

Give the sum a different name. When a variable’s type changes partway through a function, this error is waiting somewhere below.

‘function’, ‘method’, ‘builtin_function_or_method’: missing brackets#

Python
text = "hello world"
text.split[0]                       # TypeError: 'builtin_function_or_method' object is not subscriptable
text.split()[0]                     # "hello" - call it first, then index the result

items = get_items                   # assigned the function, not its result
items[0]                            # TypeError: 'function' object is not subscriptable
items = get_items()

The message is telling you that you indexed the function itself rather than what it returns. Add the call brackets.

‘type’: the class, not an instance#

Python
class Point:
    def __init__(self, x, y):
        self.coords = (x, y)

Point[0]                            # TypeError: 'type' object is not subscriptable
p = Point(1, 2)
p.coords[0]                         # 1

This also appears in type hints on old Python versions: list[int] fails on 3.8 because the built-in list was not subscriptable there. On 3.9 and later it works; on older versions use typing.List[int].

‘object’, or your own class name#

Python
class Basket:
    def __init__(self):
        self.items = []

b = Basket()
b[0]                                # TypeError: 'Basket' object is not subscriptable

Your class does not define how indexing works. Either index the attribute that holds the data, b.items[0], or make the class subscriptable by adding a __getitem__ method:

Python
class Basket:
    def __init__(self):
        self.items = []
    def __getitem__(self, index):
        return self.items[index]

Finding it quickly#

Python
print(type(value), repr(value))

Put that on the line before the failing one. The type confirms what the message said; the repr shows where the value came from. Then trace backwards to where the name was last assigned. In nearly every case the fix is on that earlier line, not on the line that raised.

Questions people ask#

What is the difference between this and “is not iterable”?

Subscriptable is about square brackets; iterable is about for loops and unpacking. An int fails both; a set is iterable but not subscriptable. Different operations, similar causes.

Why does the message say NoneType rather than None?

NoneType is the type of the single value None. The message always names the type.

Can a dictionary raise this?

Not directly; dictionaries are subscriptable. But config.get("section") returning None, followed by ["key"], raises it on the None.

How do I make my own class support brackets?

Define __getitem__, and __setitem__ for assignment. Sequence-like classes should also define __len__.

Where to go next#

Fixing 'object is not callable'Read next

Keep reading

Keep going — pick your next guide

The fastest way to improve is to read one guide, then build the thing it describes. Start with the basics, or jump straight to a project.

Ask a question or share what worked

Your email address will not be published. Required fields are marked *