{"record":{"id":"2ad3f2be1fff01bc","repo":"apache/druid","slug":"index-d-size-d-2ad3f2","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/GenericIndexed.java","lineNumber":498,"sourceCode":"      inspector.visit(\"strategy\", strategy);\n    }\n  }\n\n  /**\n   * Checks  if {@code index} a valid `element index` in GenericIndexed.\n   * Similar to Preconditions.checkElementIndex() except this method throws {@link IAE} with custom error message.\n   * <p>\n   * Used here to get existing behavior(same error message and exception) of V1 GenericIndexed.\n   *\n   * @param index index identifying an element of an GenericIndexed.\n   */\n  protected void checkIndex(int index)\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  public Class<? extends T> getClazz()\n  {\n    return strategy.getClazz();\n  }\n\n  @Override\n  public int size()\n  {\n    return size;\n  }\n\n  /**\n   * Returns the index of \"value\" in this GenericIndexed object, or (-(insertion point) - 1) if the value is not\n   * present, in the manner of Arrays.binarySearch. This strengthens the contract of Indexed, which only guarantees\n   * that values-not-found will return some negative number.","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/data/GenericIndexed.java#L480-L516","documentation":"Bounds-check guard replicating Guava's Preconditions.checkElementIndex behavior for GenericIndexed: callers attempt to read element at 'index' and this fires when index >= the number of elements stored in the index, meaning the reader requested an element beyond what was serialized into the file. It indicates an out-of-range lookup into a file-backed GenericIndexed, typically from corrupt metadata, a stale dictionary reference, or an off-by-one caller; keep index within 0..size-1.","triggerScenarios":"Calling get(index) with index >= the number of elements in the GenericIndexed, e.g. iterating with an off-by-one bound (<= size) or using stale size metadata.","commonSituations":"Loops like for (i = 0; i <= dim.size(); i++), cached/stale cardinality metadata after segment replacement, or external code assuming a larger dictionary.","solutions":["Bound loops with strict < size(), using indexed.size() rather than cached numbers.","Guard reads: if (index >= indexed.size()) return null or throw a controlled error.","Refresh any persisted cardinality/size values so they match the current segment."],"exampleFix":"// before\nfor (int i = 0; i <= indexed.size(); i++) use(indexed.get(i));\n// after\nfor (int i = 0; i < indexed.size(); i++) use(indexed.get(i));","handlingStrategy":"type-guard","validationCode":"if (index >= indexed.size()) throw new IndexOutOfBoundsException(\"index \" + index + \" >= \" + indexed.size());","typeGuard":"boolean inBounds(Indexed<?> idx, int i) { return i >= 0 && i < idx.size(); }","tryCatchPattern":"try { return indexed.get(i); } catch (IAE e) { log.warn(\"stale size metadata?\", e); return null; }","preventionTips":["Use strict '<' in loops over Indexed.size()","Refresh cached cardinality/size metadata when segments change","Fetch size from the same Indexed instance you read from"],"tags":["java","bounds-check","index"],"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-14T05:17:10.506Z"}