TypeError: 'type' object is not subscriptable (tested fix)
TypeError: 'type' object is not subscriptable usually means code with type hints like list[int] is running on Python 3.8 or older. We ran the same files on Python 3.8 and 3.13 and tested each fix.
1. list[int] in a type hint on Python 3.8 or older
The same file runs on Python 3.13 and crashes on 3.8. Annotations on a def are evaluated when the function is defined, so the error fires at import time, before you call anything:
import sys
print(sys.version.split()[0])
def total(xs: list[int]) -> int:
return sum(xs)
print(total([1, 2, 3]))
Output:
$ python3.8 b1.py
3.8.20
Traceback (most recent call last):
File "b1.py", line 3, in <module>
def total(xs: list[int]) -> int:
TypeError: 'type' object is not subscriptable
$ python3.13 b1.py
3.13.5
6
Builtin generics like list[int] became valid at runtime in Python 3.9 (PEP 585). If your laptop runs 3.11 and a server, Docker base image or CI job runs 3.8, this is the first error you see.
2. Which builtins fail
import sys
print(sys.version.split()[0])
for expr in ["list[int]", "dict[str, int]", "tuple[int, ...]", "type[int]", "set[str]"]:
try:
print(expr, "->", eval(expr))
except TypeError as e:
print(expr, "->", type(e).__name__ + ":", e)
Output:
$ python3.8 b2.py
3.8.20
list[int] -> TypeError: 'type' object is not subscriptable
dict[str, int] -> TypeError: 'type' object is not subscriptable
tuple[int, ...] -> TypeError: 'type' object is not subscriptable
type[int] -> TypeError: 'type' object is not subscriptable
set[str] -> TypeError: 'type' object is not subscriptable
$ python3.13 b2.py
3.13.5
list[int] -> list[int]
dict[str, int] -> dict[str, int]
tuple[int, ...] -> tuple[int, ...]
type[int] -> type[int]
set[str] -> set[str]
Every builtin you subscript gives the same message on 3.8. It never names which type it was, so look at the line in the traceback.
3. Fix A: from __future__ import annotations
Put this as the first statement of the module. Annotations are then stored as strings and never evaluated:
from __future__ import annotations
import sys
print(sys.version.split()[0])
def total(xs: list[int]) -> int:
return sum(xs)
print(total([1, 2, 3]))
print(total.__annotations__)
Output:
$ python3.8 b3.py
3.8.20
6
{'xs': 'list[int]', 'return': 'int'}
It only covers annotations. A type alias assigned at module level is ordinary code and still fails on 3.8:
from __future__ import annotations
import sys
print(sys.version.split()[0])
Scores = dict[str, int] # alias at module level is evaluated, not an annotation
print(Scores)
Output:
$ python3.8 b4.py
3.8.20
Traceback (most recent call last):
File "b4.py", line 4, in <module>
Scores = dict[str, int] # alias at module level is evaluated, not an annotation
TypeError: 'type' object is not subscriptable
$ python3.13 b4.py
3.13.5
dict[str, int]
Anything that evaluates the string annotations later, such as typing.get_type_hints() (which pydantic, dataclass tools and FastAPI rely on), raises the same error on 3.8:
from __future__ import annotations
import sys, typing
print(sys.version.split()[0])
def total(xs: list[int]) -> int:
return sum(xs)
try:
print(typing.get_type_hints(total))
except TypeError as e:
print(type(e).__name__ + ":", e)
Output:
$ python3.8 b7.py
3.8.20
TypeError: 'type' object is not subscriptable
$ python3.13 b7.py
3.13.5
{'xs': list[int], 'return': <class 'int'>}
4. Fix B: use typing.List and typing.Dict
The typing versions work on every Python 3 version, for annotations and aliases alike:
import sys
from typing import Dict, List
print(sys.version.split()[0])
Scores = Dict[str, int]
def total(xs: List[int]) -> int:
return sum(xs)
print(Scores, total([1, 2, 3]))
Output:
$ python3.8 b5.py
3.8.20
typing.Dict[str, int] 6
The third fix is to upgrade the interpreter to 3.9 or later. Python 3.8 reached end of life in October 2024, so this is usually the right long-term fix, and typing.List is just a bridge until then.
5. Indexing a class instead of an instance
The other common cause is writing Point[0] or cls["x"] when you meant an instance (a missing ()). Newer Pythons name the class in the message:
class Point:
pass
try:
Point[0]
except TypeError as e:
print(type(e).__name__ + ":", e)
p = Point
try:
p["x"]
except TypeError as e:
print(type(e).__name__ + ":", e)
Output:
$ python3.8 b6.py
TypeError: 'type' object is not subscriptable
TypeError: 'type' object is not subscriptable
$ python3.13 b6.py
TypeError: type 'Point' is not subscriptable
TypeError: type 'Point' is not subscriptable
On 3.11 and 3.13 the message is type 'Point' is not subscriptable; on 3.8 it is the generic 'type' object is not subscriptable. Create the instance with Point(), or add __getitem__ (or __class_getitem__ for generic classes).
6. Related: isinstance with list[int]
try:
isinstance([1, 2], list[int])
except TypeError as e:
print(type(e).__name__ + ":", e)
print(isinstance([1, 2], list))
Output:
$ python3.13 b8.py
TypeError: isinstance() argument 2 cannot be a parameterized generic
True
Even on new versions, isinstance can't check element types. Check against plain list, then check the items yourself. Related: object is not subscriptable (other types), 'NoneType' object is not subscriptable and 'dict_keys' object is not subscriptable.
Frequently asked questions
Why does list[int] give 'type' object is not subscriptable?
Builtin generics like list[int] and dict[str, int] only work at runtime from Python 3.9. On 3.8 add from __future__ import annotations, use typing.List, or upgrade.
Does from __future__ import annotations fix it everywhere?
Only in annotations. Module-level aliases like Scores = dict[str, int] and typing.get_type_hints() still raise on 3.8.
Why does my class give type 'X' is not subscriptable?
You indexed the class, not an instance. Usually a missing () when creating it.
Written with AI assistance. Measured on 2026-10-22 on Debian with Python 3.13.5 and in the official python:3.8-alpine (3.8.20) and python:3.11-alpine Docker images: builtin generics in annotations and aliases, from __future__ import annotations, typing.get_type_hints, typing.List/Dict, indexing a class, and isinstance with list[int]. Every block was run verbatim and its output pasted unedited. PlainHeaders is our extension; Python is free.