{"record":{"id":"dcae45c54ec36644","repo":"apache/druid","slug":"index-s-0-dcae45","errorCode":null,"errorMessage":"Index[%s] < 0","messagePattern":"Index\\[(.+?)\\] < 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/data/GenericIndexed.java","lineNumber":495,"sourceCode":"      // Inspecting just one example of valueBuffer, not needed to inspect the whole array, because all buffers in it\n      // are the same.\n      inspector.visit(\"valueBuffer\", valueBuffers.length > 0 ? valueBuffers[0] : null);\n      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  /**","sourceCodeStart":477,"sourceCodeEnd":513,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/data/GenericIndexed.java#L477-L513","documentation":"GenericIndexed.checkIndex() validates element access bounds; a negative index cannot address any element, so it throws IAE 'Index[i] < 0'. This guards get(int) against underflow from bad binary search results or off-by-one arithmetic.","triggerScenarios":"Calling get(index) (or lookup/indexOf paths) with a negative int, typically the result of a failed binary search/lookup returning -1 that wasn't handled.","commonSituations":"Code that treats indexOf() miss (-1) as a valid index, arithmetic like (index - 1) underflowing at 0, or deserialized metadata containing negative offsets.","solutions":["Check for negative values (especially -1 from lookup/indexOf) before calling get(index).","Clamp or return null early: if (idx < 0 || idx >= indexed.size()) return null;","Fix upstream logic so failed lookups propagate as 'not found' instead of a negative index."],"exampleFix":"// before\nint idx = indexed.indexOf(value);\nString s = indexed.get(idx);\n// after\nint idx = indexed.indexOf(value);\nString s = idx < 0 ? null : indexed.get(idx);","handlingStrategy":"type-guard","validationCode":"if (index < 0 || index >= indexed.size()) return null;","typeGuard":"boolean inBounds(Indexed<?> idx, int i) { return i >= 0 && i < idx.size(); }","tryCatchPattern":"try { return indexed.get(i); } catch (IAE e) { return null; } // treat as missing value","preventionTips":["Never feed sentinel values like -1 from indexOf/lookup straight into get()","Always compare against size() at the access site","Return Optional/null for lookup misses instead of negative indexes"],"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"}