Skip to main content

Understanding Off-by-One Errors in JavaScript

ยท 4 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

Off-by-one errors (OBOEs) are among the most common logic bugs, even for seasoned developers. These bugs occur when a loop or operation goes one iteration too far or one iteration too short-leading to incorrect results, missed elements, or crashes.

They usually occur in:

  • Loops
  • Array indexing
  • Ranges
  • Substring operations

๐Ÿ“Œ Common Scenario: Array Indexingโ€‹

In JavaScript, array indices are zero-based. That means the first element is at index 0, and the last one is at array.length - 1.

โŒ Example of an Off-by-One Errorโ€‹

const fruits = ['apple', 'banana', 'cherry'];

for (let i = 0; i <= fruits.length; i++) {
console.log(fruits[i]);
}

๐Ÿ” Problemโ€‹

This loop runs from 0 to fruits.length (which is 3), but the highest valid index is 2.
On the last iteration (i = 3), fruits[3] is undefined.


โœ… Correct Versionโ€‹

for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}

โš ๏ธ Edge Case: slice and substringโ€‹

const str = 'abcdef';
console.log(str.substring(0, 2)); // 'ab'
console.log(str.slice(0, 2)); // 'ab'

But if you do:

console.log(str.slice(0, str.length)); // โœ… full string
console.log(str.slice(0, str.length + 1)); // โŒ unnecessary, no extra character

๐Ÿง  Typical Sources of Off-by-One Errorsโ€‹

  • for loops (i <= arr.length instead of i < arr.length)
  • Substring extraction (str.slice(0, n) vs str.slice(1, n))
  • Pagination calculations
  • Cursor positions in UI logic
  • Fencepost errors (in interval boundaries)

๐Ÿงฐ How to Avoid Off-by-One Errorsโ€‹

  • Always double-check array and string lengths.
  • Use .forEach() or .map() when appropriate-they abstract away index math.
  • In for loops, remember: loop should stop before length, not at it.
  • Write unit tests for edge cases (empty arrays, single element arrays).
  • Visualize ranges explicitly ([start, end) convention).

๐Ÿงช Example: Fencepost Problemโ€‹

How many fences are needed for 5 posts?

const posts = 5;
const fences = posts - 1;

If you mistakenly write:

const fences = posts;

Youโ€™ll buy one fence too many.


๐Ÿ“Œ Summaryโ€‹

ProblemTypical CauseFix
Loop runs one too many timesi <= arr.lengthi < arr.length
Missing itemOff-by-one in index mathRecalculate with console logs
Infinite loopBoundary never reachedCheck loop condition carefully

๐Ÿง  Final Thoughtโ€‹

Off-by-one errors are simple but tricky. The best developers prevent them with:

  • Clear range reasoning
  • Index-aware iterations
  • Automated tests on edge inputs

Avoid the trap, and your code will be cleaner, safer, and more predictable.

Happy coding! ๐Ÿง‘โ€๐Ÿ’ปโœจ