{"record":{"id":"489c65cdab462d0c","repo":"apache/druid","slug":"bucketsize-must-be-a-power-of-two-but-was-d-489c65","errorCode":null,"errorMessage":"bucketSize must be a power of two but was[%,d]","messagePattern":"bucketSize must be a power of two but was\\[%,d\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/data/FrontCodedIntArrayIndexed.java","lineNumber":124,"sourceCode":"  private final int rem;\n  private final int offsetsPosition;\n  private final int bucketsPosition;\n  private final boolean hasNull;\n  private final int lastBucketNumValues;\n  private final int[] unwindPrefixLength;\n  private final int[] unwindBufferPosition;\n\n  private FrontCodedIntArrayIndexed(\n      ByteBuffer buffer,\n      ByteOrder order,\n      int bucketSize,\n      int numValues,\n      boolean hasNull,\n      int offsetsPosition\n  )\n  {\n    if (Integer.bitCount(bucketSize) != 1) {\n      throw new ISE(\"bucketSize must be a power of two but was[%,d]\", bucketSize);\n    }\n    this.buffer = buffer.asReadOnlyBuffer().order(order);\n    this.bucketSize = bucketSize;\n    this.hasNull = hasNull;\n\n    this.numBuckets = (int) Math.ceil((double) numValues / (double) bucketSize);\n    this.adjustIndex = hasNull ? 1 : 0;\n    this.adjustedNumValues = numValues + adjustIndex;\n    this.div = Integer.numberOfTrailingZeros(bucketSize);\n    this.rem = bucketSize - 1;\n    this.lastBucketNumValues = (numValues & rem) == 0 ? bucketSize : numValues & rem;\n    this.offsetsPosition = offsetsPosition;\n    this.bucketsPosition = offsetsPosition + ((numBuckets - 1) * Integer.BYTES);\n    this.unwindPrefixLength = new int[bucketSize];\n    this.unwindBufferPosition = new int[bucketSize];\n  }\n\n  @Override","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/data/FrontCodedIntArrayIndexed.java#L106-L142","documentation":"FrontCodedIntArrayIndexed's constructor requires bucketSize to be a power of two (exactly one bit set) because bucket lookup uses bit-shift arithmetic. A non-power-of-two bucketSize in the header means the data is corrupt, misaligned, or was produced by incompatible code, so it throws ISE rather than producing wrong results.","triggerScenarios":"Reading a FrontCodedIntArrayIndexed whose header yields a bucketSize like 3, 5, or 6 — from a corrupted buffer, wrong buffer offset, byte-order mismatch, or directly constructing the object with an invalid bucketSize.","commonSituations":"Corrupted segment files (disk issues, truncated copies); reading an array-typed column with mismatched offset/order assumptions; custom/direct construction with an unvalidated bucketSize; version-skew reading segments written by incompatible writers.","solutions":["Verify the segment file is not corrupted; reload or re-ingest the affected segment","Confirm the buffer position and ByteOrder match the writer when deserializing (use the standard read() factory, not direct construction)","Ensure the writer that produced the column used a validated power-of-two bucketSize","If you construct this class directly, validate first: bucketSize > 0 && Integer.bitCount(bucketSize) == 1"],"exampleFix":"// before\nnew FrontCodedIntArrayIndexed(buffer, order, 6, numValues, hasNull, offsetsPosition); // ISE\n// after\nint bucketSize = 4; // power of two, matching the writer\nnew FrontCodedIntArrayIndexed(buffer, order, bucketSize, numValues, hasNull, offsetsPosition);","handlingStrategy":"validation","validationCode":"if (bucketSize <= 0 || Integer.bitCount(bucketSize) != 1) {\n  throw new IllegalArgumentException(\"bucketSize must be a power of two: \" + bucketSize);\n}","typeGuard":null,"tryCatchPattern":"try {\n  FrontCodedIntArrayIndexed idx = FrontCodedIntArrayIndexed.read(buffer, order);\n} catch (IllegalStateException e) {\n  // corrupted or misaligned buffer; reload or re-ingest the segment\n}","preventionTips":["Use the standard read() factory for deserialization; avoid direct construction","Validate power-of-two bucketSize on the writing side before serializing","Check buffer offsets and ByteOrder when reading raw column buffers","Treat this error as a corruption signal: restore the segment from backup or re-ingest"],"tags":["corruption","serialization","validation"],"backgroundTag":"invalid-argument-value","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"}