Ramblings of an aging IT geek
← Ramblings of an aging IT geek
debugging

The Off-by-One That Three of Us Approved

A classic fencepost error slipped past two reviewers and me, because the loop looked exactly like every correct loop we'd ever read.

A terminal with a stack trace

A pagination bug shipped last week that dropped the last record on every page. Not the first one, the last, which is the kind of error you only notice when someone counts. The loop used < total where it wanted <= total after an earlier change shifted the indexing by one. Textbook fencepost.

What stings is that three of us looked at it. Two reviewers and me. The diff was small and tidy, the loop looked exactly like every correct loop any of us had read ten thousand times, and that familiarity is precisely the trap. Your eye sees the shape "for i less than length" and ticks the box, because that shape is correct roughly always. Except this time the bounds had moved underneath it and nobody re-derived them from scratch.

The fix was one character. The lesson, again, is that code review catches the unfamiliar far better than the familiar-but-wrong. A test that asserted the exact record count would have caught it in seconds, and that's what we added. Eyes are good at "this looks odd". They are useless at "this looks completely normal and is off by one". For that you need something that actually counts, because none of us were going to.