trekhleb/javascript-algorithms · error · Error

Left index can not be greater than right one

Error message

Left index can not be greater than right one

What it means

FenwickTree.queryRange(leftIndex, rightIndex) returns the inclusive sum over [leftIndex, rightIndex] as query(rightIndex) - query(leftIndex - 1), and it first rejects leftIndex > rightIndex with this error because a reversed pair would produce a nonsense negative-range result. Both bounds are ultimately fed to query(), so they must also respect the tree's 1-based domain 1..arraySize. The error is pure argument-order validation, not a state problem.

Source

Thrown at src/data-structures/tree/fenwick-tree/FenwickTree.js:63

    let sum = 0;

    for (let i = position; i > 0; i -= (i & -i)) {
      sum += this.treeArray[i];
    }

    return sum;
  }

  /**
   * Query sum from index leftIndex to rightIndex.
   *
   * @param  {number} leftIndex
   * @param  {number} rightIndex
   * @return {number}
   */
  queryRange(leftIndex, rightIndex) {
    if (leftIndex > rightIndex) {
      throw new Error('Left index can not be greater than right one');
    }

    if (leftIndex === 1) {
      return this.query(rightIndex);
    }

    return this.query(rightIndex) - this.query(leftIndex - 1);
  }
}

View on GitHub (pinned to 85293e3e2b)

Solutions

  1. Normalize the pair before calling: queryRange(Math.min(a, b), Math.max(a, b)).
  2. If your convention is half-open [from, to), translate: queryRange(from + 1, to) with 1-based bounds — and return 0 for empty ranges instead of letting bounds cross.
  3. Validate both bounds against the tree domain: leftIndex >= 1 && rightIndex <= tree.arraySize && leftIndex <= rightIndex.

Example fix

// before
function rangeSum(a, b) {
  return ft.queryRange(a, b); // throws when a > b
}

// after
function rangeSum(a, b) {
  const [left, right] = a <= b ? [a, b] : [b, a];
  return ft.queryRange(left, right);
}
Defensive patterns

Strategy: validation

Validate before calling

function safeRangeSum(tree, leftIndex, rightIndex) {
  const left = Math.min(leftIndex, rightIndex);
  const right = Math.max(leftIndex, rightIndex);
  if (left < 1 || right > tree.arraySize) {
    throw new RangeError(`range must be inside [1, ${tree.arraySize}]`);
  }
  return tree.queryRange(left, right);
}

Prevention

When it happens

Trigger: Swapping the two arguments, e.g. queryRange(right, left); treating the range as [exclusive, inclusive] and passing rightIndex = leftIndex - 1 for what should be an empty range; clamping bounds with Math.max and Math.min in the wrong order so a degenerate range arrives reversed.

Common situations: Adapting a caller whose range convention is [start, end) to this tree's inclusive [start, end]; user-supplied range inputs (date windows, slice bounds) not normalized before the call; refactors that rename left/right parameters and swap their call sites.

Related errors


AI-assisted analysis of trekhleb/javascript-algorithms@85293e3e2b (2026-08-24). Data as JSON: /api/errors/53e4a6b662d3cf94. Report an issue: GitHub.