IndexError: string index out of range
1 · The lesson
readWhat this error means
You indexed into a string at a position that doesn't exist. Strings, like lists, are zero-indexed sequences: "abc"[0] is 'a', "abc"[2] is 'c', and "abc"[3] raises IndexError. An empty string "" has no valid indices at all.
When you see it
>>> name = "Margaret" >>> name[10] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: string index out of range
Why it happens
It almost always happens in parsing code that assumes a fixed structure: a date string that is always YYYY-MM-DD, a postcode that is always 6 characters, a filename that always has an extension. When the input is even one character shorter, the index you assumed is past the end.
How to fix it
1. Validate length first:
def first_letter(s): if len(s) == 0: return "" return s[0]
2. Use slicing. Slices never raise IndexError:
year = date_str[:4] # safe even if date_str is shorter suffix = filename[-3:] # safe on any string
setup added so this can run · defines date_str, filename
date_str = ["alpha", "beta", "gamma"] filename = ["alpha", "beta", "gamma"]
3. Use functions designed for the job instead of your own indexing:
# fragile ext = filename[filename.index(".") + 1:] # robust import os ext = os.path.splitext(filename)[1].lstrip(".")
setup added so this can run · defines filename
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) filename = _AutoMock('filename')
4. Catch the error when you parse input you can't predict:
try: initial = user_input[0].upper() except IndexError: initial = "?"
setup added so this can run · defines user_input
user_input = ["alpha", "beta", "gamma"]
When you'd see this in real code
- Reading a CSV where one row has an empty first field:
row[0][0]fails becauserow[0]is"". - Parsing a phone number assuming a country code prefix:
number[1:4]is fine, butnumber[0]raises on an empty string. - Going through a string character by character with a counter in a
whileloop, and the counter goes past the end. Usefor ch in s:orenumerate(s)instead.
Related errors
See Also
- All Python errors: the full index, by type and by when it happens.
- String cheat sheet
- Strings and slicing tutorial
Found this useful? Share it with a friend who’s learning Python.