IndexError

seq[i] where i is not between -len(seq) and len(seq) - 1. Slices never raise it — only single-position access does.

InheritsBaseException›Exception›LookupError›IndexError
Lookup exceptionPython 3 (all)Live demo
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

NameTypeRequiredDescription
*argsobjectnoUsually one message string. Stored in e.args; str(e) is that message.

Attributes

AttributeTypeMeaning
argstupleThe constructor arguments — for built-in sequences, one message string. IndexError has no attribute holding the bad index.
__context__BaseException | NoneThe exception being handled when this one was raised (implicit chaining).
__cause__BaseException | NoneSet 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 range
2. Too far negative
[1, 2, 3][-4]
Returns
IndexError: list index out of range
3. Empty string, first character
line = '' line[0]
Returns
IndexError: string index out of range
4. Missing field after split()
'a,b'.split(',')[2]
Returns
IndexError: list index out of range
5. pop() on an empty list
[].pop()
Returns
IndexError: pop from empty list
6. Tuples and ranges name themselves
(1, 2)[2]
Returns
IndexError: tuple index out of range
7. 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
IndexError

Pitfalls

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.