IndexError
seq[i] where i is not between -len(seq) and len(seq) - 1. Slices never raise it — only single-position access does.
IndexError(*args)
Raised by
seq[i], seq[i] = x, del seq[i], list.pop(), list.pop(i)
Message
'<type> index out of range' / 'pop from empty list'
Quick fix
check len(seq) first, or use seq[-1] / a slice
Watch out
last valid index is len(seq) - 1, not len(seq)
Demo
Live evaluation
Index a 3-item list. Valid positions are 0..2 counting from the front and -1..-3 from the back.
Try:
Inputs
iintindex to read
Code
items = ['a', 'b', 'c'] items[0]
Result
'a'
In Trigger, 3 fails but -3 works: negative indexes count from the end, so the valid range is -len..len-1. The message names the type (list index out of range), and pop() on an empty list has its own wording. In Raise, note that the custom class rejects -1 — negative indexing is not automatic; a class only gets it if __getitem__ implements it.
Constructor
| Name | Type | Required | Description |
|---|---|---|---|
| *args | object | no | Usually one message string. Stored in e.args; str(e) is that message. |
Attributes
| Attribute | Type | Meaning |
|---|---|---|
| args | tuple | The constructor arguments — for built-in sequences, one message string. IndexError has no attribute holding the bad index. |
| __context__ | BaseException | None | The exception being handled when this one was raised (implicit chaining). |
| __cause__ | BaseException | None | Set by raise ... from ... |
Common patterns
Last item without counting
seq[-1] is the last element — no len() arithmetic to get wrong. It still raises on an empty sequence.
last = items[-1] if items else None
Optional field from split()
Parsed lines often have fewer fields than expected. Check the length instead of indexing blindly.
parts = line.split(',') email = parts[2] if len(parts) > 2 else ''
Pad with a slice
Slices clamp to the sequence bounds, so unpacking a padded slice never raises IndexError.
first, second = (row + [None, None])[:2]
First item or default
next() with a default avoids both IndexError on [] and building a list at all.
first = next(iter(results), None)
Examples
1. One past the end
[1, 2, 3][3]
Returns
IndexError: list index out of range2. Too far negative
[1, 2, 3][-4]
Returns
IndexError: list index out of range3. Empty string, first character
line = ''
line[0]
Returns
IndexError: string index out of range4. Missing field after split()
'a,b'.split(',')[2]
Returns
IndexError: list index out of range5. pop() on an empty list
[].pop()
Returns
IndexError: pop from empty list6. Tuples and ranges name themselves
(1, 2)[2]
Returns
IndexError: tuple index out of range7. Slices never raise
[1, 2, 3][1:10]
Returns
[2, 3]8. Caught as LookupError
try:
'abc'[10]
except LookupError as e:
print(type(e).__name__)
Returns
IndexErrorPitfalls
1. len(seq) is not a valid index
Indexes start at 0, so a 3-item list ends at index 2. Use -1 for the last item.
items[len(items)]
items = ['a', 'b', 'c'] items[len(items)]
IndexError: list index out of range
items[-1]
items = ['a', 'b', 'c'] items[-1]
'c'
2. Removing items while looping by index
range(len(nums)) is computed once; every pop() shortens the list, so later indexes run off the end.
pop inside range loop
nums = [1, 2, 3, 4] for i in range(len(nums)): if nums[i] % 2 == 0: nums.pop(i)
IndexError: list index out of range
Build a new list
nums = [1, 2, 3, 4] nums = [n for n in nums if n % 2] nums
[1, 3]
3. Assigning past the end does not grow a list
Unlike JavaScript arrays or dicts, lists do not create slots on assignment. Append instead.
nums[2] = 3
nums = [1, 2] nums[2] = 3
IndexError: list assignment index out of range
append()
nums = [1, 2] nums.append(3) nums
[1, 2, 3]
When to use
Use it
- Raising it from your own __getitem__ for an out-of-range position
- Catching it around a pop() on a stack or queue that may be empty
- EAFP access where an out-of-range index is genuinely exceptional
Reach for something else
- Reading the last item → seq[-1] (guarded by if seq)
- Optional trailing fields → check len() or pad with a slice
- Missing dict key → that is KeyError; catch LookupError for both
Notes
Per-type text
The message names the type: list, tuple, string, range object, bytearray, array index out of range; bytes says just "index out of range"
Catch via
except LookupError catches IndexError and KeyError
Huge index
An index beyond the C ssize_t range raises IndexError: cannot fit 'int' into an index-sized integer
Not an int
A str or float index raises TypeError (list indices must be integers or slices), not IndexError
FAQ
You asked for a position the list does not have. A list of length n has indexes 0 to n - 1, and -1 to -n from the end. The most common causes are using len(items) as an index, reading items[0] from an empty list, and indexing a split() result that has fewer fields than expected.