{"record":{"id":"a0e9837d10c8aac1","repo":"apache/druid","slug":"size-d-expansion-length-d-or-0","errorCode":null,"errorMessage":"Size[%d] > expansion.length[%d] or < 0","messagePattern":"Size\\[(.+?)\\] > expansion\\.length\\[(.+?)\\] or < 0","errorType":"exception","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/data/ArrayBasedIndexedInts.java","lineNumber":57,"sourceCode":"  }\n\n  public ArrayBasedIndexedInts(int[] expansion)\n  {\n    this.expansion = expansion;\n    this.size = expansion.length;\n  }\n\n  public void ensureSize(int size)\n  {\n    if (expansion.length < size) {\n      expansion = new int[size];\n    }\n  }\n\n  public void setSize(int size)\n  {\n    if (size < 0 || size > expansion.length) {\n      throw new IAE(\"Size[%d] > expansion.length[%d] or < 0\", size, expansion.length);\n    }\n    this.size = size;\n  }\n\n  /**\n   * Sets the values from the given array. The given values array is not reused and not prone to be mutated later.\n   * Instead, the values from this array are copied into an array which is internal to ArrayBasedIndexedInts.\n   */\n  public void setValues(int[] values, int size)\n  {\n    if (size < 0 || size > values.length) {\n      throw new IAE(\"Size[%d] should be between 0 and %d\", size, values.length);\n    }\n    ensureSize(size);\n    System.arraycopy(values, 0, expansion, 0, size);\n    this.size = size;\n  }\n","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/data/ArrayBasedIndexedInts.java#L39-L75","documentation":"ArrayBasedIndexedInts.setSize(int) validates that the requested active size is non-negative and does not exceed the capacity of the internal expansion array, throwing IAE otherwise. It is used to reuse the object over a fixed backing array.","triggerScenarios":"Calling setSize with a negative value or a value larger than the array passed at construction (expansion.length), e.g. from initColumnValues with a bigger row than the allocated array.","commonSituations":"Reusing a pooled ArrayBasedIndexedInts across rows/columns with mismatched capacities; off-by-one or wrong initial allocation size.","solutions":["Ensure the backing array passed to the constructor is at least as large as the maximum size set","Call ensureSize(size) before setSize to grow the internal array","Validate size >= 0 before calling"],"exampleFix":"// before\nindexedInts.setSize(values.length);\n// after\nindexedInts.ensureSize(values.length);\nindexedInts.setSize(values.length);","handlingStrategy":"validation","validationCode":"if (size >= 0 && size <= expansion.length) { indexed.setSize(size); }","typeGuard":"boolean canSetSize(ArrayBasedIndexedInts v, int size) { return size >= 0 && size <= v.size() || size <= v.inspectArrayCapacity(); } // use documented capacity","tryCatchPattern":"try { indexed.setSize(size); } catch (IAE e) { indexed.ensureSize(size); indexed.setSize(size); }","preventionTips":["Call ensureSize before setSize","Match backing-array allocation to maximum row size","Clamp sizes to [0, capacity] in reuse/pooling code"],"tags":["java","index-out-of-range","segments"],"backgroundTag":"value-out-of-range","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}