{"record":{"id":"53e4a6b662d3cf94","repo":"trekhleb/javascript-algorithms","slug":"left-index-can-not-be-greater-than-right-one","errorCode":null,"errorMessage":"Left index can not be greater than right one","messagePattern":"Left index can not be greater than right one","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/data-structures/tree/fenwick-tree/FenwickTree.js","lineNumber":63,"sourceCode":"    let sum = 0;\n\n    for (let i = position; i > 0; i -= (i & -i)) {\n      sum += this.treeArray[i];\n    }\n\n    return sum;\n  }\n\n  /**\n   * Query sum from index leftIndex to rightIndex.\n   *\n   * @param  {number} leftIndex\n   * @param  {number} rightIndex\n   * @return {number}\n   */\n  queryRange(leftIndex, rightIndex) {\n    if (leftIndex > rightIndex) {\n      throw new Error('Left index can not be greater than right one');\n    }\n\n    if (leftIndex === 1) {\n      return this.query(rightIndex);\n    }\n\n    return this.query(rightIndex) - this.query(leftIndex - 1);\n  }\n}\n","sourceCodeStart":45,"sourceCodeEnd":73,"githubUrl":"https://github.com/trekhleb/javascript-algorithms/blob/85293e3e2b88f4d2ce330d956b139cf628aa1e82/src/data-structures/tree/fenwick-tree/FenwickTree.js#L45-L73","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Normalize the pair before calling: queryRange(Math.min(a, b), Math.max(a, b)).","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.","Validate both bounds against the tree domain: leftIndex >= 1 && rightIndex <= tree.arraySize && leftIndex <= rightIndex."],"exampleFix":"// before\nfunction rangeSum(a, b) {\n  return ft.queryRange(a, b); // throws when a > b\n}\n\n// after\nfunction rangeSum(a, b) {\n  const [left, right] = a <= b ? [a, b] : [b, a];\n  return ft.queryRange(left, right);\n}","handlingStrategy":"validation","validationCode":"function safeRangeSum(tree, leftIndex, rightIndex) {\n  const left = Math.min(leftIndex, rightIndex);\n  const right = Math.max(leftIndex, rightIndex);\n  if (left < 1 || right > tree.arraySize) {\n    throw new RangeError(`range must be inside [1, ${tree.arraySize}]`);\n  }\n  return tree.queryRange(left, right);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize user-supplied ranges once, at the API boundary: order the endpoints, clamp to [1, arraySize], and return 0 for empty ranges.","Write down each function's range convention (this tree is inclusive [left, right]) next to the call site.","Unit-test degenerate ranges: single element (l === r), full range, and reversed inputs.","Prefer queryRange(l, r) over hand-rolled query(r) - query(l - 1) so the order guard always applies."],"tags":["fenwick-tree","binary-indexed-tree","argument-validation","range-query","data-structures"],"backgroundTag":"invalid-argument-range","analyzedSha":"85293e3e2b88f4d2ce330d956b139cf628aa1e82","analyzedAt":"2026-08-24T05:59:10.417Z","schemaVersion":2},"datasetVersion":"2026-08-24T07:17:09.176Z"}