Skip to main content

Off-by-one errors and loops

6 min readUpdated

An off-by-one error is when a loop runs one time too many or one time too few, or an index is one place out. It is one of the most common bugs in student code, and also one of the easiest to catch once you test the edges.

Why it happens

  • Python lists start at index 0, so the last index is len(items) - 1.
  • range(a, b) includes a but stops before b.
  • < and <= look similar but change the count by one.
  • Pseudocode FOR i ← 1 TO 10 includes 10, but range(1, 10) does not.

Classic examples

Too manypython
nums = [4, 8, 15]
for i in range(len(nums) + 1):   # one too many
    print(nums[i])                # IndexError when i = 3
Too fewpython
for i in range(1, 10):   # prints 1 to 9, not 1 to 10
    print(i)

for i in range(1, 11):   # prints 1 to 10
    print(i)
< versus <=python
count = 0
while count < 5:      # runs 5 times
    count += 1

count = 0
while count <= 5:     # runs 6 times
    count += 1

Counting fence posts

A fence 10 metres long with a post every metre needs 11 posts, not 10. The same idea appears when counting the items between two indexes: from index 3 to index 7 inclusive there are 7 - 3 + 1 = 5 items.

How to avoid them

  • Loop over items directly with for x in items when you do not need the index.
  • Use enumerate(items) when you need both index and value.
  • Test with the smallest cases: an empty list, one item, two items.
  • Trace the first and last time round the loop in a trace table.
  • Check slices: items[1:4] gives indexes 1, 2 and 3.
Safe numbering with enumeratepython
names = ["Asha", "Ben", "Chen"]
for position, name in enumerate(names, start=1):
    print(position, name)
You wantWrite
0 to n-1range(n)
1 to nrange(1, n + 1)
n down to 1range(n, 0, -1)
Every index of a listrange(len(items))

Frequently asked questions

Why does Python's range stop before the end?

So that range(n) gives exactly n values and matches list indexes 0 to n-1.

How do I spot an off-by-one error quickly?

Run your code on tiny inputs and check the first and last values processed.

Do off-by-one errors happen in binary search?

Yes, very often. Be clear whether your bounds are inclusive and update them with mid + 1 or mid - 1.

Practise this, step by step

Short lessons with quizzes, practice and interview questions, from your first program to job-ready.

Object-Oriented Programming course: syllabus and 1:1 mentoringClasses, encapsulation, inheritance, polymorphism, interfaces, SOLID and design patterns.