KeyError: 0 in Python and pandas (tested fix)
KeyError: 0 means something looked up the key or label 0 and it does not exist. In pandas that is usually s[0] after a filter or df[0] meant as "first row". With plain dicts, it is often an int key that JSON turned into the string "0". We reproduced each case and tested the fix.
1. pandas: s[1] after filtering looks up a label
# pandas: s[0] / df[0] look up a LABEL, not a position
import pandas as pd
df = pd.DataFrame({"name": ["a", "b", "c"], "n": [5, 1, 7]})
big = df[df["n"] > 2] # filtering keeps the original index labels
print(big.index.tolist())
try:
big["name"][1]
except KeyError as e:
print("KeyError:", e)
print(big["name"].iloc[1]) # position
print(big.reset_index(drop=True)["name"][1])
Output:
[0, 2]
KeyError: 1
c
c
With a Series, s[0] means "the row whose index label is 0", not "the first row". Filtering, dropna(), sort_values() and groupby keep the original labels, so label 0 (or 1) may no longer exist and you get KeyError: 0. Use .iloc[n] for positions, or reset_index(drop=True) to renumber.
2. pandas: df[0] looks up a column
import pandas as pd
df = pd.DataFrame({"name": ["a", "b"], "n": [5, 1]})
try:
df[0] # columns are "name" and "n", not 0
except KeyError as e:
print("KeyError:", e)
print(df.iloc[0].tolist()) # first row
print(df.iloc[:, 0].tolist()) # first column
print(pd.__version__)
Output:
KeyError: 0
['a', np.int64(5)]
['a', 'b']
3.1.0
On a DataFrame, df[0] asks for a column named 0. Columns are usually strings, so this fails at once. df.iloc[0] is the first row and df.iloc[:, 0] the first column. Tested with pandas 3.1.0.
3. pandas: [0] on an empty result
# Empty results: [0] on an empty dict-like or Series
import pandas as pd
s = pd.Series([1, 2, 3])
empty = s[s > 10]
try:
empty[0]
except KeyError as e:
print("KeyError:", e)
print(empty.iloc[0] if len(empty) else "no rows")
Output:
KeyError: 0
no rows
A filter that matches nothing returns an empty Series, and any lookup on it fails. .iloc[0] raises IndexError rather than KeyError, so check len() (or .empty) first.
4. Plain dicts: int keys after a JSON round trip
# JSON object keys are always strings: int keys don't survive a round trip
import json
scores = {0: "alice", 1: "bob"}
loaded = json.loads(json.dumps(scores))
print(loaded)
try:
loaded[0]
except KeyError as e:
print("KeyError:", e)
print(loaded["0"])
fixed = {int(k): v for k, v in loaded.items()}
print(fixed[0])
Output:
{'0': 'alice', '1': 'bob'}
KeyError: 0
alice
alice
JSON object keys are always strings, so {0: ...} comes back from json.loads as {"0": ...} and d[0] fails although the printed dict looks right. Convert the keys once after loading. More look-alike key traps: KeyError but the key exists.
Related: KeyError: all causes ยท name 'pd' is not defined.
Frequently asked questions
Why does pandas raise KeyError: 0?
s[0] and df[0] look up the label 0, not the first position. After filtering or sorting, label 0 may be gone; use .iloc[0] for the first row.
How do I get the first row of a DataFrame?
df.iloc[0]. df[0] asks for a column named 0 and raises KeyError: 0.
Why does my dict raise KeyError: 0 after loading JSON?
JSON keys are always strings, so the key is now '0'. Convert with {int(k): v for k, v in d.items()}.
Written with AI assistance. Measured on 2026-10-23 in the python:3-alpine Docker image (Python 3.14, pandas 3.1.0): s[1] after a filter, df[0], [0] on an empty Series, and int dict keys after json.dumps/json.loads. Every block was run verbatim and its output pasted unedited. PlainHeaders is our extension; Python and pandas are free.