// Python
IndexError: list assignment index out of range in Python: the fix
Every example on this page was run on 4 November 2026 in Python 3.14, and the output under each one is what it printed. How we test these posts.
IndexError: list assignment index out of range means you wrote items[i] = value for a position the list does not have yet. A Python list never grows when you assign past its end, so items[0] = 1 fails on an empty list. The most common fix is items.append(value). When you need fixed positions, create the list at full size first with [None] * n.
What does list assignment index out of range mean?
list assignment index out of range means the index on the left of an = is equal to or bigger than the list’s length. Assignment can only replace an item that already exists. An empty list has no positions at all, so even scores[0] = 90 fails:
scores = []
scores[0] = 90
print(scores)
scores = []
scores[0] = 90
print(scores)Output
Traceback (most recent call last):
File "main.py", line 2, in <module>
scores[0] = 90
~~~~~~^^^
IndexError: list assignment index out of rangeThe word “assignment” tells you the failing line writes to the list. When the line reads from it instead, as in print(scores[0]), Python says list index out of range without the word “assignment”.
How do I fix list assignment index out of range?
Use append() to add an item to the end of a list. append() makes the list one longer each time, so there is no position to get wrong:
scores = []
scores.append(90)
scores.append(75)
print(scores)
print(len(scores))
scores = []
scores.append(90)
scores.append(75)
print(scores)
print(len(scores))Output
[90, 75] 2
Use items[i] = value only to replace an item that is already there, such as scores[1] = 80 once scores holds two items. To add several items at once, scores.extend([60, 85]) appends each of them in order.
Why do I get list assignment index out of range in a for loop?
A for loop gives list assignment index out of range when it fills a new, empty list by position. The loop counts 0, 1, 2 over the source list, but the target list is still empty, so its first pass already fails:
prices = [10, 20, 30]
doubled = []
for i in range(len(prices)):
doubled[i] = prices[i] * 2
print(doubled)
prices = [10, 20, 30]
doubled = []
for i in range(len(prices)):
doubled[i] = prices[i] * 2
print(doubled)Output
Traceback (most recent call last):
File "main.py", line 4, in <module>
doubled[i] = prices[i] * 2
~~~~~~~^^^
IndexError: list assignment index out of rangeBuild the new list with append() inside the loop, or with a list comprehension, which builds the whole list in one expression and is the usual Python way:
prices = [10, 20, 30]
doubled = []
for price in prices:
doubled.append(price * 2)
print(doubled)
tripled = [price * 3 for price in prices]
print(tripled)
prices = [10, 20, 30]
doubled = []
for price in prices:
doubled.append(price * 2)
print(doubled)
tripled = [price * 3 for price in prices]
print(tripled)Output
[20, 40, 60] [30, 60, 90]
Neither version needs an index, and both work for a source list of any length, including an empty one.
How do I create a list of a fixed size in Python?
Create a list of a fixed size with [None] * n, or [0] * n for numbers. Every position from 0 to n - 1 then exists, and you can assign to any of them in any order. A common slip is [] * n, which repeats an empty list and is still empty:
print(len([] * 5))
slots = [None] * 5
slots[3] = "booked"
slots[0] = "booked"
print(slots)
print(len([] * 5))
slots = [None] * 5
slots[3] = "booked"
slots[0] = "booked"
print(slots)Output
0 ['booked', None, None, 'booked', None]
When you do not know the size in advance, grow the list to fit before assigning. extend() adds the missing positions, filled with a value you choose:
def set_at(items, i, value, fill=None):
if i >= len(items):
items.extend([fill] * (i + 1 - len(items)))
items[i] = value
slots = []
set_at(slots, 2, "c")
set_at(slots, 0, "a")
print(slots)
def set_at(items, i, value, fill=None):
if i >= len(items):
items.extend([fill] * (i + 1 - len(items)))
items[i] = value
slots = []
set_at(slots, 2, "c")
set_at(slots, 0, "a")
print(slots)Output
['a', None, 'c']
Why do I get list assignment index out of range in a 2D list?
A 2D list gives list assignment index out of range when its rows are shorter than the column you assign to. grid[1][2] = 5 needs row 1 to exist and to have a position 2. A grid built as a list of empty rows has neither columns nor room to add them by index:
grid = [[], []]
grid[1][2] = 5
print(grid)
grid = [[], []]
grid[1][2] = 5
print(grid)Output
Traceback (most recent call last):
File "main.py", line 2, in <module>
grid[1][2] = 5
~~~~~~~^^^
IndexError: list assignment index out of rangeBuild every row at full width with a list comprehension. Do not write [[0] * cols] * rows: that repeats one row object, so a change to one row shows up in all of them:
rows, cols = 2, 3
grid = [[0] * cols for _ in range(rows)]
grid[1][2] = 5
print(grid)
shared = [[0] * cols] * rows
shared[1][2] = 5
print(shared)
rows, cols = 2, 3
grid = [[0] * cols for _ in range(rows)]
grid[1][2] = 5
print(grid)
shared = [[0] * cols] * rows
shared[1][2] = 5
print(shared)Output
[[0, 0, 0], [0, 0, 5]] [[0, 0, 5], [0, 0, 5]]
If the row itself is missing, as in grid[2][0] = 5 on a grid of two rows, the read of grid[2] fails first, and the message is list index out of range without “assignment”.
Why does del give list assignment index out of range?
del items[i] gives list assignment index out of range when position i does not exist, because Python treats deleting an item as a kind of assignment to it. Check the length first, or use pop(), which names itself in its error:
items = ["a", "b", "c"]
del items[1]
print(items)
del items[3]
items = ["a", "b", "c"]
del items[1]
print(items)
del items[3]Output
['a', 'c']
Traceback (most recent call last):
File "main.py", line 4, in <module>
del items[3]
~~~~~^^^
IndexError: list assignment index out of rangeWhy does insert not give list assignment index out of range?
list.insert() never raises list assignment index out of range. An index past the end puts the item at the end, so insert(10, "d") on a list of three adds "d" as the fourth item, not the eleventh. A program that uses insert() to place items at fixed positions runs without an error and puts them in the wrong place:
items = ["a", "b", "c"]
items.insert(10, "d")
print(items)
print(items.index("d"))
items = ["a", "b", "c"]
items.insert(10, "d")
print(items)
print(items.index("d"))Output
['a', 'b', 'c', 'd'] 3
The Python tutorial on lists describes insert(), append() and extend(), and the mutable sequence operations table lists what s[i] = x and del s[i] do.
Should I use a dict instead of a list?
Use a dict instead of a list when the positions are labels, such as user IDs, years or seat numbers, and many of them are empty. A dict accepts any new key on assignment, so there is no out of range case and no None placeholders:
seats = {}
seats[14] = "Ava"
seats[3] = "Noah"
print(seats)
print(seats.get(7))
seats = {}
seats[14] = "Ava"
seats[3] = "Noah"
print(seats)
print(seats.get(7))Output
{14: 'Ava', 3: 'Noah'}
NoneReading a key that is not there with seats[7] raises KeyError, so read with seats.get(7) when a missing key is normal. The IndexError entry in the Python docs covers the list side of the rule.
How do I catch list assignment index out of range before it happens?
No linter flags items[i] = value on a short list, because the length is only known when the program runs. Keep to one habit instead: assign by index only to a list created at full size, and build every other list with append(), extend() or a comprehension. When the error does appear, print len(items) next to the index on the line before it.
Related errors
IndexError: list index out of range is the read version of the same mistake, with its own causes in for loops and on empty lists, in the list index out of range post. TypeError: 'str' object does not support item assignment comes from word[0] = "x": a string cannot be changed in place at all, so build a new one. If the list is None, as after items = items.sort(), Python raises TypeError: ‘NoneType’ object is not subscriptable on a read.