The IndexError: list index out of range error means your Python code is trying to access an element in a list using an index that doesn’t exist. This usually happens when the index is negative, or greater than or equal to the length of the list.
Here are the most common culprits and how to fix them:
1. Off-by-One Error in Loops:
- Diagnosis: You’re iterating over a list and using the loop counter as an index, but the loop runs one iteration too many.
- Command/Check:
my_list = [10, 20, 30] for i in range(len(my_list) + 1): # Incorrect: range goes up to len(my_list) print(my_list[i]) - Fix: Adjust the
rangeto go up tolen(my_list).my_list = [10, 20, 30] for i in range(len(my_list)): # Correct: range goes up to len(my_list) - 1 print(my_list[i]) - Why it works:
range(n)generates numbers from 0 up ton-1. List indices are also 0-based. Iflen(my_list)is 3, valid indices are 0, 1, and 2.range(3)gives 0, 1, 2.range(4)gives 0, 1, 2, 3, andmy_list[3]is out of bounds.
2. Accessing an Empty List:
- Diagnosis: Your code assumes a list has elements when it’s actually empty.
- Command/Check:
data = [] print(data[0]) - Fix: Always check if a list is empty before accessing its elements.
data = [] if data: # This checks if the list is not empty print(data[0]) else: print("The list is empty.") - Why it works: An empty list evaluates to
Falsein a boolean context. Theif data:condition prevents execution ofdata[0]if the list is empty.
3. Incorrect Index Calculation:
- Diagnosis: You’re calculating an index based on some logic, and that calculation results in an invalid index. This is common with user input or dynamic data.
- Command/Check:
Ifvalues = [1, 2, 3, 4, 5] user_input = "3" # Imagine this came from input() index_to_access = int(user_input) print(values[index_to_access])user_inputwas"5",int("5")is 5, andvalues[5]would fail. - Fix: Validate the calculated index against the list’s bounds.
values = [1, 2, 3, 4, 5] user_input = "5" index_to_access = int(user_input) if 0 <= index_to_access < len(values): print(values[index_to_access]) else: print(f"Index {index_to_access} is out of bounds for list of length {len(values)}.") - Why it works: This explicitly checks if the computed
index_to_accessfalls within the valid range of0tolen(values) - 1before attempting the access.
4. Using Negative Indices Incorrectly:
- Diagnosis: While negative indices are valid for accessing elements from the end of a list (e.g.,
my_list[-1]is the last element), using a negative index that is "too negative" will cause anIndexError. - Command/Check:
my_list = ['a', 'b', 'c'] print(my_list[-4]) # This will fail - Fix: Ensure negative indices are within the valid range of
-len(my_list)to-1.my_list = ['a', 'b', 'c'] index_to_access = -4 if -len(my_list) <= index_to_access < 0: print(my_list[index_to_access]) else: print(f"Negative index {index_to_access} is out of bounds for list of length {len(my_list)}.") - Why it works: For a list of length 3, valid negative indices are -1, -2, and -3. An index of -4 is attempting to go beyond the first element. The check ensures the negative index is not smaller than
-len(my_list).
5. Modifying a List While Iterating:
- Diagnosis: Removing elements from a list while iterating over it with indices can cause subsequent indices to point to the wrong elements or go out of bounds.
- Command/Check:
Whennumbers = [1, 2, 3, 4, 5] for i in range(len(numbers)): if numbers[i] % 2 == 0: numbers.pop(i) # This is problematic print(numbers)numbers[i]is 2 (at index 1),pop(1)removes 2. The list becomes[1, 3, 4, 5]. The loop then moves toi=2, which now points to4(it was originally at index 3). Ifnumbers[i]was 4 (at index 2), andpop(2)removes it, the list becomes[1, 3, 5]. The loop then moves toi=3, which is out of bounds. - Fix: Iterate over a copy of the list, or iterate in reverse, or build a new list.
Or, build a new list:numbers = [1, 2, 3, 4, 5] for i in range(len(numbers) - 1, -1, -1): # Iterate backwards if numbers[i] % 2 == 0: numbers.pop(i) print(numbers) # Output: [1, 3, 5]numbers = [1, 2, 3, 4, 5] odd_numbers = [num for num in numbers if num % 2 != 0] print(odd_numbers) # Output: [1, 3, 5] - Why it works: Iterating backward ensures that removing an element doesn’t affect the indices of elements you haven’t visited yet. Building a new list avoids modification altogether.
6. Indexing into a List of Lists with Incorrect Dimensions:
- Diagnosis: When dealing with nested lists (like a 2D matrix), you might provide too many or too few indices, or indices that are out of bounds for the inner lists.
- Command/Check:
matrix = [[1, 2], [3, 4]] print(matrix[0][2]) # Will fail if inner list only has 2 elements print(matrix[2][0]) # Will fail if outer list only has 2 elements - Fix: Ensure you have the correct number of indices and that each index is within the bounds of its respective list.
matrix = [[1, 2], [3, 4]] row_index = 0 col_index = 1 if 0 <= row_index < len(matrix) and 0 <= col_index < len(matrix[row_index]): print(matrix[row_index][col_index]) else: print("Invalid indices for matrix.") - Why it works: This performs bounds checking at each level of nesting, ensuring that both the row and column indices are valid for the given
matrixstructure.
The next error you’ll likely encounter after fixing IndexError is a KeyError if you’re using dictionaries, or a TypeError if you’re trying to perform operations on incompatible data types.