Off-by-one errors in Python and JavaScript
The loop that runs one time too many, the slice that drops the last item, the index that starts in the wrong place.
What is off-by-one error?
An off-by-one error is a loop bound, index or count that is wrong by exactly one. The logic is right; the arithmetic is one step out. They are among the most common bugs in programming precisely because they hide so well — the code produces almost the right answer, which is far harder to notice than no answer at all.
Why it happens
Almost every off-by-one comes from mixing two counting conventions in the same expression. Array indices start at 0 but lengths start at 1. Python's range() and JavaScript's slice() exclude their upper bound, while a phrase like "items 1 to 10" includes both ends. Whenever those conventions meet without a deliberate conversion, something ends up one out.
How to recognise it
- The result is right except for the first or last element.
- A sum comes out as NaN in JavaScript, because reading past the end gave undefined.
- IndexError in Python at exactly the final iteration.
- It works for even-sized input and breaks for odd, or vice versa.
Errors and symptoms this causes
- IndexError: list index out of range
- IndexError: string index out of range
- Cannot read properties of undefined
- loop runs one extra time
- last item missing from array
How to fix it
Test the smallest case by hand. A list of length n has indices 0 to n-1; a window of size k fits n - k + 1 times; n items need n - 1 separators. Write the boundary case as a test before you write the loop, because the boundary is exactly where these live and exactly what casual testing skips.
Practise off-by-one errors
Working code with one bug in it. Find it, fix it in the browser, and see the explanation. No account needed.