Skip to content
spot_the_ai_bug

Off-by-one errors: interview questions

An off-by-one error uses a boundary that's one step too far or too short: <= instead of <, length instead of length - 1, or an inclusive range where an exclusive one was needed.

How to spot it in code review

  • Check every loop bound against the valid index range.
  • Ask whether each range is inclusive or exclusive, and whether the code agrees.
  • Test the first, last and empty cases mentally.
  • Watch for 0-indexed code documented as 1-indexed, or vice versa.

Why AI-generated code gets this wrong

Models have seen both conventions thousands of times and blend them, writing the documentation for one and the arithmetic for the other.

Off-by-one errors: 3 practice questions

Getting the last element

latestMessage() should return the newest message in the chat. Why is the preview always empty?

function latestMessage(messages) {  if (messages.length === 0) return null;  const last = messages[messages.length];  return last.text;}
Show answer

line 3 · Off-by-one

Arrays are zero-indexed, so the last element is at length - 1. messages[messages.length] is undefined, and reading .text on it throws a TypeError.

Fix
  const last = messages[messages.length - 1]; // or messages.at(-1)

Interview follow-up: Bonus points for mentioning Array.prototype.at(-1).

Q2Javaeasy

Summing an array

total() adds up a cart's line items. Why does it throw on every call?

public static long total(long[] lineItemsCents) {    long sum = 0;    for (int i = 0; i <= lineItemsCents.length; i++) {        sum += lineItemsCents[i];    }    return sum;}
Show answer

line 3 · Off-by-one

Valid indexes run from 0 to length - 1. With <= the loop reads index length on its last pass and throws ArrayIndexOutOfBoundsException.

Fix
    for (int i = 0; i < lineItemsCents.length; i++) {

Interview follow-up: An enhanced for loop (for (long c : lineItemsCents)) removes the index, and the bug, entirely.

Q3SQLmedium

January revenue with BETWEEN

This should total all orders placed in January. Finance says the number is too low. Why? (created_at is a TIMESTAMP.)

SELECT SUM(total_cents) AS january_revenueFROM ordersWHERE created_at BETWEEN '2025-01-01' AND '2025-01-31';
Show answer

line 3 · Off-by-one

'2025-01-31' means midnight at the start of Jan 31, and BETWEEN is inclusive of exactly that instant. Every order placed later on Jan 31 is excluded.

Fix
WHERE created_at >= '2025-01-01'  AND created_at <  '2025-02-01';

Interview follow-up: Half-open ranges (>= start, < next start) work for every precision and avoid end-of-month arithmetic.

Every day, everyone gets the same pull request written by AI. It looks clean. It has comments. It has exactly one real bug.

  1. 1

    Find the line

    Tap the buggy line, then hit Submit. You get 3 attempts.

  2. 2

    Read the hints

    A miss within 2 lines is 🔥 Warm. Anything further is ❄️ Cold.

  3. 3

    Name the bug

    Found it? Bonus round: pick the bug type from 4 options. It doesn't affect your win, just your bragging rights.

// your share card

found in 3/3

🟥 cold miss · 🟨 warm miss · 🟩 found · ⬛ unused

Keyboard: ↑ ↓ to move between lines, Enter to submit. A new bug drops every day at midnight IST.

0
Played
0
Win %
0
Streak
0
Max

Attempts distribution