You run your script. Python stops and prints this:
IndexError: list index out of range Your code asked a list for an item at a position that isn't there. That's all it means. Below are the six situations that cause it in real programs, a fix for each, and what the same error looks like for tuples and strings. I tested every example on Python 3.11, 3.12 and 3.14. All three print the same message.
What the Error Means
Positions in a list are called indexes, and they start at 0, not 1. A list with 3 items has the indexes 0, 1 and 2. Ask for index 3 and it fails, because there's no fourth item. You can also count from the end with negative numbers. -1 is the last item. -3 is the first item of a three-item list. Go too far back and you get the same error:
items = [10, 20, 30] print(items[-1], items[-3]) # 30 10 print(items[-4]) # IndexError: list index out of range How to Find the Cause Fast
Start with the traceback. It points at the exact line. Look at the index and the list on that line and ask yourself which one is wrong. Print both right before the failing line and you'll see:
print(len(items), i) If the index is equal to the length or bigger, the index is too high. If the length is 0, the list is empty. Nearly every case is one of the six below.
The Six Causes
1. Off by One: Using len() as an Index
names = ["Ana", "Ben", "Cy"] print(names[len(names)]) The last valid index is len(names) - 1, not len(names). It's the classic off-by-one mistake. The easiest fix is index -1, which always means the last item:
names = ["Ana", "Ben", "Cy"] print(names[len(names) - 1]) print(names[-1]) 2. range(len(x) + 1)
scores = [90, 80, 70] for i in range(len(scores) + 1): print(scores[i]) Here range(len(scores) + 1) gives you 0, 1, 2 and 3. The list only goes up to index 2. So the first three prints work and the fourth one crashes. That's why this bug is easy to miss. The best fix is to skip indexes and loop over the items themselves:
scores = [90, 80, 70] for score in scores: print(score) # If you need the position as well, use enumerate: for i, score in enumerate(scores): print(i, score) 3. The List Is Empty
results = [] print(results[0]) An empty list has no index 0. You'll hit this when a search, a filter or a file read finds nothing and your code assumed it would find something. Before you grab an item, check that the list has content:
results = [] if results: print(results[0]) else: print("no results") An empty list counts as false in an if. So if results: reads as “if there is at least one item”.
4. sys.argv[1] Without an Argument
import sys filename = sys.argv[1] print("opening", filename) sys.argv holds the command-line arguments. Index 0 is the script's own name. Run python bug.py with nothing after it and there's no index 1. Count the arguments first, and tell the user what to type:
import sys if len(sys.argv) < 2: sys.exit("usage: python fixed.py FILENAME") filename = sys.argv[1] print("opening", filename) With no argument, it prints usage: python fixed.py FILENAME. Run it as python fixed.py notes.txt and it prints opening notes.txt.
5. split() Gave Fewer Parts Than You Expected
line = "Ana 17" parts = line.split() name, age, city = parts[0], parts[1], parts[2] print(name, age, city) "Ana 17".split() returns two parts, yet the code reaches for a third. Input from users, files and websites often has fewer pieces than you planned for. Take the parts that are always there. Give the optional ones a default:
line = "Ana 17" name, age, *rest = line.split() city = rest[0] if rest else "unknown" print(name, age, city) 6. Removing Items While Looping Over Indexes
nums = [1, 2, 3, 4, 5, 6] for i in range(len(nums)): if nums[i] % 2 == 0: nums.pop(i) print(nums) range(len(nums)) is worked out once, when the loop starts. It counts up to 5 whatever happens later. But pop() shrinks the list as you go, so sooner or later the loop asks for an index that no longer exists. Don't change a list while you loop over its positions. Build a new one instead:
nums = [1, 2, 3, 4, 5, 6] odds = [n for n in nums if n % 2 != 0] print(odds) The Same Mistake on Other Types
Tuples and strings index the same way, but each words the error a bit differently. I ran all of these on Python 3.14:
| The code | What Python says |
|---|---|
[1, 2][5] | IndexError: list index out of range |
(1, 2)[5] | IndexError: tuple index out of range |
"ab"[5] | IndexError: string index out of range |
[].pop() | IndexError: pop from empty list |
{"a": 1}["b"] | KeyError: 'b' |
The last row is a different error. A missing dictionary key raises KeyError, not IndexError. The fixes above won't help there.
Should You Use try/except?
You can catch the error instead of preventing it:
results = [] try: first = results[0] except IndexError: first = None print(first) This prints None. It works well when a missing item is normal and expected. The risk is that it can hide a real bug, like a loop that runs one step too far. For causes 1, 2 and 6, fix the code. Don't catch the error.
Which Cause Is It?
| What you see | Cause | Fix |
|---|---|---|
The index equals len(x) | Off by one | Use len(x) - 1 or -1 |
The error comes on the last pass of a for i in range(...) loop | The range is too long | Loop over the items, or use enumerate |
len(x) is 0 | Empty list | Check if x: first |
The line reads sys.argv[1] | No argument given | Check len(sys.argv) |
The line unpacks the result of split() | Too few parts | Unpack with *rest and a default |
The loop calls pop() or remove() on the list it loops over | The list shrinks | Build a new list |
The Rule, Stated Once
IndexError means the position you asked for isn't in the list. Positions start at 0, so the last one is len - 1. Check the length before you index. Loop over items, not positions. And never shrink a list while you loop over its indexes.
Want more Python errors with a clear cause? Try UnboundLocalError: Variable Referenced Before Assignment, ModuleNotFoundError After pip install, Tkinter TclError: Image Doesn’t Exist and PySerial: module ‘serial’ has no attribute ‘Serial’. Just starting with Python? Read Python for Beginners and Python modules first.
Download the code: you'll find the broken and fixed versions of all six causes on GitHub in Python-projects/Troubleshooting/indexerror. Run any file with python bug.py from inside its folder.
Originally published on my blog. I post new C, Python and AI-agent guides there regularly.

