apache/druid · error · IllegalStateException

bucketSize must be a power of two but was[%,d]

Error message

bucketSize must be a power of two but was[%,d]

What it means

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.

Solutions

  1. Verify the segment file is not corrupted; reload or re-ingest the affected segment
  2. Confirm the buffer position and ByteOrder match the writer when deserializing (use the standard read() factory, not direct construction)
  3. Ensure the writer that produced the column used a validated power-of-two bucketSize
  4. If you construct this class directly, validate first: bucketSize > 0 && Integer.bitCount(bucketSize) == 1

Example fix

// before
new FrontCodedIntArrayIndexed(buffer, order, 6, numValues, hasNull, offsetsPosition); // ISE
// after
int bucketSize = 4; // power of two, matching the writer
new FrontCodedIntArrayIndexed(buffer, order, bucketSize, numValues, hasNull, offsetsPosition);
Defensive patterns

Strategy: validation

Validate before calling

if (bucketSize <= 0 || Integer.bitCount(bucketSize) != 1) {
  throw new IllegalArgumentException("bucketSize must be a power of two: " + bucketSize);
}

Try / catch

try {
  FrontCodedIntArrayIndexed idx = FrontCodedIntArrayIndexed.read(buffer, order);
} catch (IllegalStateException e) {
  // corrupted or misaligned buffer; reload or re-ingest the segment
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/489c65cdab462d0c. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/data/FrontCodedIntArrayIndexed.java:124

  private final int rem;
  private final int offsetsPosition;
  private final int bucketsPosition;
  private final boolean hasNull;
  private final int lastBucketNumValues;
  private final int[] unwindPrefixLength;
  private final int[] unwindBufferPosition;

  private FrontCodedIntArrayIndexed(
      ByteBuffer buffer,
      ByteOrder order,
      int bucketSize,
      int numValues,
      boolean hasNull,
      int offsetsPosition
  )
  {
    if (Integer.bitCount(bucketSize) != 1) {
      throw new ISE("bucketSize must be a power of two but was[%,d]", bucketSize);
    }
    this.buffer = buffer.asReadOnlyBuffer().order(order);
    this.bucketSize = bucketSize;
    this.hasNull = hasNull;

    this.numBuckets = (int) Math.ceil((double) numValues / (double) bucketSize);
    this.adjustIndex = hasNull ? 1 : 0;
    this.adjustedNumValues = numValues + adjustIndex;
    this.div = Integer.numberOfTrailingZeros(bucketSize);
    this.rem = bucketSize - 1;
    this.lastBucketNumValues = (numValues & rem) == 0 ? bucketSize : numValues & rem;
    this.offsetsPosition = offsetsPosition;
    this.bucketsPosition = offsetsPosition + ((numBuckets - 1) * Integer.BYTES);
    this.unwindPrefixLength = new int[bucketSize];
    this.unwindBufferPosition = new int[bucketSize];
  }

  @Override

View on GitHub (pinned to 9b90983fd2)