{"record":{"id":"c0c4742e2a421723","repo":"apache/druid","slug":"index-d-size-d-c0c474","errorCode":null,"errorMessage":"Index[%d] >= size[%d]","messagePattern":"Index\\[(.+?)\\] >= size\\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/data/Indexed.java","lineNumber":127,"sourceCode":"    return false;\n  }\n\n  /**\n   * Checks  if {@code index} is between 0 and {@code size}. Similar to Preconditions.checkElementIndex() except this\n   * method throws {@link IAE} with custom error message.\n   * <p>\n   * Used here to get existing behavior(same error message and exception) of V1 {@link GenericIndexed}.\n   *\n   * @param index identifying an element of an {@link Indexed}\n   * @param size size of the {@link Indexed}\n   */\n  static void checkIndex(int index, int size)\n  {\n    if (index < 0) {\n      throw new IAE(\"Index[%s] < 0\", index);\n    }\n    if (index >= size) {\n      throw new IAE(\"Index[%d] >= size[%d]\", index, size);\n    }\n  }\n}\n","sourceCodeStart":109,"sourceCodeEnd":131,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/data/Indexed.java#L109-L131","documentation":"Indexed.checkIndex validates that an index used to look up an element in an Indexed collection is within [0, size). The library throws this IAE whenever index >= size to fail fast rather than reading out of bounds from the underlying data structure. The odd format is a quirk: '%s' would be more accurate than the mismatched '%d' on the first argument, but the values are index and size.","triggerScenarios":"Calling Indexed.get(index) (or via IndexedInts/IndexedLongs accessor paths) with an index equal to or greater than the collection's size(), or a stale index held after the column shrank or was re-read.","commonSituations":"Row-by-row iteration using a cached row count from a different segment version; off-by-one loops (i <= size()); reading a column after the segment was replaced or partially loaded.","solutions":["Print the collection's size() next to the offending index and fix the loop bound to `index < size()`","Ensure the size you bound iteration by comes from the same Indexed instance you call get() on","Check for off-by-one errors (i <= size() instead of i < size())","If indexes come from another column (e.g. IndexedInts offsets), validate them against this collection's size before lookup"],"exampleFix":"// before\nfor (int i = 0; i <= indexed.size(); i++) { process(indexed.get(i)); }\n// after\nfor (int i = 0; i < indexed.size(); i++) { process(indexed.get(i)); }","handlingStrategy":"validation","validationCode":"if (index < 0 || index >= indexed.size()) { throw new IllegalArgumentException(\"index \" + index + \" out of range, size=\" + indexed.size()); }","typeGuard":"boolean inBounds(Indexed<?> col, int i) { return col != null && i >= 0 && i < col.size(); }","tryCatchPattern":"try { value = indexed.get(i); } catch (IllegalArgumentException e) { log.error(\"index %d out of bounds (size=%d)\", i, indexed.size()); throw e; }","preventionTips":["Always iterate with i < indexed.size()","Derive loop bounds from the same object you call get() on","Avoid caching sizes across segment reloads"],"tags":["indexing","druid","segment"],"backgroundTag":"index-out-of-bounds","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}