Debugging — Python Error Guide

IndexError —
The index walked one step too far.

You asked a list for an index that doesn't exist — usually one past the last valid position. It's the single most common off-by-one bug in Python, and it almost always comes from a loop bound that's wrong by exactly one. Watch the index march past the list's last valid position on LearnBug and see precisely where it goes wrong.

IndexErrorException type
len(list)-1Last valid index
PythonLanguage

What is IndexError?

Python raises IndexError: list index out of range when you access my_list[i] with an i that's outside the valid range. For a list of length n, valid indices run from 0 to n-1 — asking for index n (or higher, or a negative index beyond -n) is always out of bounds.

Why visualization helps

The bug is in the loop's boundary, not in whatever line the traceback points to — and boundaries are exactly what's hardest to eyeball correctly. LearnBug shows the index value at every iteration next to the list itself, so you can see the exact iteration where it steps past the last valid position.

LearnBug — the loop index marching past the last valid position
🖼 Add a LearnBug screenshot here
What Causes It

Three ways an index goes out of bounds

range(len(list) + 1)

Adding +1 (often by accident, or from confusing "number of elements" with "last valid index") makes the loop try one index past the end.

Loop bound

list[i + 1] near the end of a loop

Comparing each element to its neighbor (common in sorting algorithms) reads one index ahead — on the very last element, that neighbor doesn't exist.

Look-ahead

An empty or shorter-than-expected list

Accessing list[0] assuming there's at least one element — but the list turned out to be empty, so even index 0 is out of range.

Empty input
Walkthrough

Looping through [85, 92, 78] with range(len(scores) + 1)

1

i=0: scores[0] = 85 — valid, prints fine

The list has 3 elements, valid indices 0, 1, 2. Index 0 is well within range.

85i=0
92
78
scores[0] = 85 ✓ valid
2

i=1, i=2: scores[1]=92, scores[2]=78 — both still valid

Index 2 is the last valid index for a 3-element list. Everything up to here is fine.

85
92i=1
78i=2, last valid
scores[1] = 92, scores[2] = 78 — both valid
3

i=3: because range(len(scores) + 1) = range(4), the loop tries one more index

len(scores) is 3, so range(len(scores) + 1) produces 0, 1, 2, 3 — four values for a three-element list. Index 3 doesn't exist.

85
92
78
?i=3, doesn't exist!
scores[3] → no such index — the list only has indices 0, 1, 2
4

scores[3] raises IndexError immediately

Python checks bounds on every single index access — there's no silent "return None" or default value, it raises right at the moment of access.

Result: IndexError: list index out of range ✗ — the +1 in the range call is the bug

Code Example

The broken code, and the traceback it produces

PythonBroken — off-by-one loop bound
scores = [85, 92, 78]

for i in range(len(scores) + 1):   # +1 goes one index too far
    print(scores[i])
TracebackWhat Python actually prints
85
92
78
Traceback (most recent call last):
  File "scores.py", line 4, in <module>
    print(scores[i])
              ~~~~~~^^^
IndexError: list index out of range
The Fix

Loop over range(len(...)) — no +1 — or just iterate directly

PythonFixed — two ways
scores = [85, 92, 78]

# Fix 1: drop the +1
for i in range(len(scores)):
    print(scores[i])

# Fix 2: if you don't actually need the index, iterate directly
for score in scores:
    print(score)

Quick Reference

Error classIndexErrorRaised when a sequence index is outside its valid range
Typical causeLoop bound off by onerange(len(x) + 1), or reading list[i+1] on the last element
Fix patternrange(len(x)) or direct iterationOnly use index-based loops when you actually need the index
Safe alternativeenumerate()for i, value in enumerate(scores) gets both index and value without manual range math

Frequently asked questions

What's the last valid index for a list of length n?

n - 1. A list of 3 elements has valid indices 0, 1, 2 — never 3. This is the single fact behind almost every IndexError: len(list) tells you the count of elements, not the last valid index, which is always one less.

Why doesn't Python just return None for an out-of-range index like some other operations do?

Silently returning a default value for a clearly invalid index would hide real bugs — you'd get wrong results instead of a clear error telling you exactly what went wrong. This is Python's general design philosophy of failing loudly rather than guessing at what you meant.

How does negative indexing interact with this error?

Negative indices count from the end — list[-1] is the last element, equivalent to list[len(list)-1]. The valid negative range is -len(list) to -1; anything more negative than -len(list) raises the same IndexError, for the same underlying reason.

Is enumerate() actually safer than a manual range(len(...)) loop?

Yes — enumerate(scores) can never produce an out-of-range index because it's generated directly from iterating the list itself, not from a separately computed range. It also reads more clearly when you need both the index and the value, which is the most common reason to reach for an index-based loop in the first place.

Watch your own loop's index, step by step

Paste your code into LearnBug and see exactly where the index steps out of bounds.

Open Playground →