liveBook · Manning

Off-by-one error

As explained in 100 Java Mistakes and How to Avoid Them

An off-by-one error is a boundary error in which an iteration or indexing operation starts or stops one position or value too early or too late.

An off-by-one error is a boundary mistake in which an index or iteration starts or stops one position too early or too late. An index equal to an array, list, or string length is invalid, because valid positions stop below that length. section 5.2

Common Java forms include:

  • Accessing an element before checking that the string is nonempty or that the index is valid. section 5.2
  • Using a reversed relation, such as checking data.length < index when the intended condition concerns index < data.length. section 5.2
  • Rejecting index values greater than length while accidentally accepting index == length. section 5.2
  • Reversing a loop but keeping i++ instead of i--, or using hi instead of hi - 1 as the initial index. section 3.6

A backward loop with the correct boundary

A forward loop over [lo, hi) includes lo and excludes hi. Its descending equivalent is `for (int i = hi - 1; i >= lo; i--)`. Starting at hi accesses one position beyond the range; incrementing i can make the loop run zero times or continue until integer overflow. section 3.6

void processString(String s) {
  if (Character.isDigit(s.charAt(0))) {
    processStringStartingWithDigit(s);
  }
}

Inspect the minimal empty-string failure: charAt(0) executes before any check that a character exists. section 5.2

for (int i = hi - 1; i >= lo; i--)

Compare the canonical descending loop against incorrect initial values, bounds, or update directions. section 3.6

Check bounds before indexing, and make the valid interval explicit. For a contiguous range, require nonnegative length, offset, and count, with count <= length - offset; this avoids overflow in offset + count. Java also provides Objects.checkIndex, checkFromToIndex, and checkFromIndexSize for standard validation. section 5.2

Static analysis can catch many access-before-check and wrong-direction-loop cases. IntelliJ IDEA and SonarLint detect update-direction mismatches, while PVS-Studio can flag the index-equals-length case. Complex index expressions may require intermediate variables, and intentional bounds choices still need review. section 5.2 section 3.6

How 100 Java Mistakes and How to Avoid Them covers it

How deep it goes
Explains failure modes, corrected loop forms, overflow-safe range checks, and analyzer limits without developing complete programs.
Examples
Uses empty strings, arrays, lists, contiguous ranges, descending for loops, and Java range-checking methods.
What it assumes
Assumes Java array, string, list, index, and for-loop syntax while illustrating boundary behavior through focused examples.
What you can do after
Diagnose and prevent boundary bugs with explicit checks, corrected loop bounds, Java validation methods, and targeted analyzers.
How it connects
Connects array indexing, string indexing, list access, bounds checking, reverse iteration, integer overflow, and static analysis.

Also explained in

Compare how 4 books explain off-by-one error →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Java Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.