Bug class · off-by-one errors

How to spot off-by-one errors in code review

An off-by-one error is a boundary that is one step wrong: the last item is never processed, a value exactly on the threshold falls on the wrong side. The code works for every input except the one at the edge, which is why tests that use round numbers miss it.

What it looks like in a diff

A loop bound or a division that stops one short: range(len(items) - 1), i < n - 1, a count divided without rounding up, a slice whose end excludes the item it should include.

A comparison at a stated threshold: the requirement says "18 or over" and the code says > 18, or a range is supposed to include its last day and the code compares against the start of that day. Read the requirement's wording ("up to", "at least", "through") and check the operator against it.

Questions to ask in review

How to word the comment

Name the input, the path it takes and what goes wrong, then the fix. For example (on an imagined PR, not one from the library):

The loop runs over days 0 to 5, so Sunday's numbers never make it into the weekly report. Loop over all seven days (range(7)), and add a test with data on the last day.

Practise on real PRs

As of October 2026, the DiffDojo library has 15 live PRs that plant off-by-one errors, across 7 stacks. They are not listed here: a PR you open knowing its bug teaches less. Each review is graded on whether you find the bug and explain it.

Open the library

Read more

All bug classes · Review guides by stack · Glossary