Fix IndexError in Python
Error Reference
IndexError: list index out of range
You accessed a position that doesn't exist. Here's how to avoid it.
Out-of-range access
A list of length n has valid indexes 0 through n - 1. Asking for anything past that raises the error:
colors = ['red', 'green', 'blue']
print(len(colors)) # 3
print(colors[2]) # blue -- the last valid index is len - 1
print(colors[3])
Traceback (most recent call last):
File "colors.py", line 4, in <module>
print(colors[3])
~~~~~~^^^
IndexError: list index out of range
The mismatch to internalize: len(colors) is 3, but the last element lives at index 2. Whenever you see this error, compare the index you used against len(items) - 1.
The off-by-one loop
The classic bug is looping one step too far with a manual index:
items = ['a', 'b', 'c']
for i in range(len(items) + 1): # produces 0, 1, 2, 3
print(items[i]) # IndexError when i == 3
range(len(items)) already stops at the last valid index — the + 1 overshoots. But the better fix is to stop managing indexes by hand:
items = ['a', 'b', 'c']
for item in items: # no index, no off-by-one
print(item)
for i, item in enumerate(items): # when you genuinely need the index
print(i, item)
Negative indexes
Negative indexes count from the end: -1 is the last element, -len(items) is the first. They go out of range just like positive ones:
colors = ['red', 'green', 'blue']
print(colors[-1]) # blue
print(colors[-3]) # red
print(colors[-4]) # IndexError: list index out of range
On an empty list every index is out of range, including -1 — there is no "last element" to point at. That's why items[-1] is a common crash site for functions that receive empty input.
Safe patterns
Check emptiness (or length) before indexing:
items = []
if items:
last = items[-1]
else:
last = None
Slicing never raises — out-of-range slices are clamped to what exists:
letters = ['a', 'b']
print(letters[5:]) # []
print(letters[:10]) # ['a', 'b']
print(letters[5:9]) # []
And next() with a default gives you "first element or fallback" in one line:
items = []
first = next(iter(items), None)
print(first) # None -- no exception
Frequently Asked Questions
Why does items[-1] fail on an empty list?
Index -1 means "the last element", and an empty list has no elements at all — so there is nothing for -1 to refer to and Python raises IndexError. Guard with a truthiness check, or use a conditional expression.
items = []
last = items[-1] if items else None
What is the difference between IndexError and KeyError?
IndexError comes from sequences (lists, tuples, strings) when a numeric position is out of range. KeyError comes from mappings (dicts) when a key is absent. Both subclass LookupError, so except LookupError catches either.
try:
value = container[selector]
except LookupError: # catches IndexError and KeyError
value = None
Does slicing raise IndexError?
No. Slices clamp to the bounds of the sequence, so a slice that starts past the end simply returns an empty list. This makes slicing a safe way to take "up to N" elements without checking the length first.
print([1, 2][10:20]) # []
print([1, 2, 3][:100]) # [1, 2, 3]