Home/Blog/Python

// Python

IndexError: list index out of range in Python, and how to fix it

IndexError: list index out of range means you asked a list for a position it does not have. A list of three items has positions 0, 1 and 2, so asking for [3] fails. Python stops at that line and names it, which makes this one of the easier errors to fix once you know where to look.

What it looks like

scores = [90, 75, 60]
print(scores[0])
print(scores[3])

Output

90
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(scores[3])
          ~~~~~~^^^
IndexError: list index out of range

The last line of the traceback is the error, and the line above it is the code that failed. Here it is scores[3] on line 3.

The four usual causes

1. Counting from one. Positions start at zero, so the last item of a list is at len(items) - 1, not len(items). Python has a shorter way to ask for it: items[-1].

2. A loop that goes one step too far. range(len(items) + 1) or a hand-written counter that runs past the end:

scores = [90, 75, 60]
for i in range(len(scores) + 1):
    print(scores[i])

Output

90
75
60
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(scores[i])
          ~~~~~~^^^
IndexError: list index out of range

Loop over the list itself instead, and there is no index to get wrong:

scores = [90, 75, 60]
for score in scores:
    print(score)

Output

90
75
60

When you need the position as well, enumerate gives you both: for i, score in enumerate(scores):.

3. An empty list. Code that reads items[0] works until the day the list is empty. Check first:

results = []
first = results[0] if results else None
print(first)

Output

None

4. Changing a list while looping over its positions. Removing items shortens the list, but range(len(items)) was worked out before the loop started. Build a new list instead of deleting from the one you are looping over: kept = [x for x in items if x > 0].

Negative positions stop somewhere too

Counting from the end is how items[-1] reaches the last item, but that range has an edge as well. A list of three has -1, -2 and -3, and one step further fails the same way. So does -1 on an empty list, which is why the empty-list check above matters here too:

scores = [90, 75, 60]
print(scores[-1], scores[-3])
print(scores[-4])

Output

60 90
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(scores[-4])
          ~~~~~~^^^^
IndexError: list index out of range

When a short list is normal

Sometimes the list is meant to be short, such as the results of a search that found nothing. Then there is no off-by-one to fix, and catching the error is a fair answer. Keep the try around the one line that can fail, and say what happens when it does:

scores = [90, 75, 60]
try:
    print(scores[3])
except IndexError:
    print("no fourth score")

Output

no fourth score

Wrapping a whole function in try hides real bugs along with the error you expected, so use this only where a short or empty list is an ordinary case.

The quick way to find the bad index

Print the length and the index just before the line that fails:

scores = [90, 75, 60]
i = 3
print(len(scores), i)

Output

3 3

If the index is equal to or bigger than the length, that is your error.