Python List Comprehension IndexError: 5 Causes (2026)

You wrote [a[i] + b[i] for i in range(len(a))] and got IndexError because list b is shorter than a. Or you nested loops and the inner list had a different length than expected. List comprehensions don’t fail more often than regular loops, but the one-liner format hides the bug until runtime.

Python List Comprehension IndexError 5 Causes (2026)
Python List Comprehension IndexError 5 Causes (2026)

📌 Quick answer: Replace for i in range(len(a)) with zip(a, b) when iterating two lists in parallel. zip auto-stops at the shorter list. For positional access use enumerate. Both prevent the most common comprehension IndexError patterns.

Cause 1: Mismatched parallel lists with range(len(a))

The most common bug pattern.

a = [1, 2, 3, 4, 5]
b = [10, 20, 30]

# ❌ IndexError on b[3]
result = [a[i] + b[i] for i in range(len(a))]

# ✓ zip auto-stops at shorter list
result = [x + y for x, y in zip(a, b)]    # [11, 22, 33]

Cause 2: Nested loop accessing outer list by index

Common in 2D matrix code.

matrix = [[1, 2], [3, 4, 5], [6]]

# ❌ matrix[1] has 3 items, matrix[2] has 1
flat = [matrix[i][j] for i in range(3) for j in range(2)]

# ✓ iterate inner lists directly
flat = [item for row in matrix for item in row]

Cause 3: Conditional access on possibly-empty inner list

The conditional comes too late, after the index.

data = [{"items": [1, 2]}, {"items": []}, {"items": [9]}]

# ❌ data[1]["items"][0] doesn't exist
firsts = [d["items"][0] for d in data]

# ✓ guard inside the comprehension
firsts = [d["items"][0] for d in data if d["items"]]

Prevention

  1. Use zip() for parallel iteration, never for i in range(len(a))
  2. Use enumerate(items) for “index + value” instead of range(len)
  3. Add an if clause inside comprehension to filter out empty/missing rows
  4. Test with mismatched / empty inputs in unit tests

Frequently Asked Questions

Why use zip() instead of range(len())?

zip auto-handles different-length inputs by stopping at the shorter one. range(len(a)) only knows about a’s length and will index out of b if b is shorter. zip is also more readable and Pythonic.

How do I iterate with index and value together?

Use enumerate(items): for i, v in enumerate(items). It’s cleaner than for i in range(len(items)) and avoids the IndexError trap when items length changes between iterations.

Can I add a try/except inside a list comprehension?

Not directly; comprehensions don’t support try/except. Refactor to a helper function: def safe(d, k): try: return d[k][0]; except (IndexError, KeyError): return None. Then [safe(d, ‘items’) for d in data].

How do I flatten a 2D list safely?

[item for row in matrix for item in row]. The two for clauses iterate the structure directly, no indexing required, never raises IndexError.

What’s the difference between zip and itertools.zip_longest?

zip stops at the shortest input. zip_longest continues to the longest, padding shorter inputs with a fillvalue (default None). Use zip when shorter is acceptable, zip_longest when you need every element from the longest.

Leave a Comment