apache/druid · error · IllegalArgumentException

bucketSize must be a power of two (from 1 up to 128) but…

Error message

bucketSize must be a power of two (from 1 up to 128) but was[%,d]

What it means

FrontCodedIntArrayIndexedWriter requires the bucketSize used for front-coding int arrays to be a power of two between 1 and 128 inclusive. The constructor validates Integer.bitCount(bucketSize)==1 (single bit set) and range before allocating the bucket buffer, throwing IAE otherwise. Bucket size drives the front-coding block layout, so non-power-of-two or oversized values cannot be represented.

Solutions

  1. Set bucketSize to a power of two in [1,128]: 1, 2, 4, 8, ..., 128 (e.g. 128).
  2. Round user config to the nearest valid power of two before constructing: bucketSize = Integer.highestOneBit(Math.max(1, Math.min(raw, 128))).
  3. Fix the JSON/column config source so the literal value passed down is valid.

Example fix

// before
int bucketSize = config.getBucketSize(); // e.g. 100
writer = new FrontCodedIntArrayIndexedWriter(medium, ByteOrder.nativeOrder(), bucketSize);
// after
int raw = config.getBucketSize();
int bucketSize = Integer.highestOneBit(Math.max(1, Math.min(raw, 128)));
writer = new FrontCodedIntArrayIndexedWriter(medium, ByteOrder.nativeOrder(), bucketSize);
Defensive patterns

Strategy: validation

Validate before calling

static int normalizeBucketSize(int raw) {
  if (raw >= 1 && raw <= 128 && Integer.bitCount(raw) == 1) return raw;
  throw new IllegalArgumentException("bucketSize must be a power of two in [1,128], got " + raw);
}

Type guard

boolean isValidBucketSize(int n) { return n >= 1 && n <= 128 && Integer.bitCount(n) == 1; }

Prevention

When it happens

Trigger: Calling new FrontCodedIntArrayIndexedWriter(medium, byteOrder, bucketSize) with bucketSize = 0, negative, > 128, or any value that is not a power of two (e.g. 3, 6, 100, 129).

Common situations: A user-supplied 'frontCodedArrayBucketSize' segment or column config typo (e.g. 100 instead of 128), computed bucket sizes from heuristics that don't round to powers of two, or off-by-one (0 or 129).

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/d3cb67b24b3d5399. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/data/FrontCodedIntArrayIndexedWriter.java:96

  private WriteOutBytes valuesOut = null;
  private int numWritten = 0;
  private ByteBuffer scratch;
  private int logScratchSize = 10;
  private boolean isClosed = false;
  private boolean hasNulls = false;

  private int readCachedBucket = -1;
  @Nullable
  private ByteBuffer readBufferCache = null;

  public FrontCodedIntArrayIndexedWriter(
      SegmentWriteOutMedium segmentWriteOutMedium,
      ByteOrder byteOrder,
      int bucketSize
  )
  {
    if (Integer.bitCount(bucketSize) != 1 || bucketSize < 1 || bucketSize > 128) {
      throw new IAE("bucketSize must be a power of two (from 1 up to 128) but was[%,d]", bucketSize);
    }
    this.segmentWriteOutMedium = segmentWriteOutMedium;
    this.scratch = ByteBuffer.allocate(1 << logScratchSize).order(byteOrder);
    this.bucketSize = bucketSize;
    this.byteOrder = byteOrder;
    this.bucketBuffer = new int[bucketSize][];
    this.getOffsetBuffer = ByteBuffer.allocate(Integer.BYTES).order(byteOrder);
    this.div = Integer.numberOfTrailingZeros(bucketSize);
  }

  @Override
  public void open() throws IOException
  {
    headerOut = segmentWriteOutMedium.makeWriteOutBytes();
    valuesOut = segmentWriteOutMedium.makeWriteOutBytes();
  }

  @Override

View on GitHub (pinned to 9b90983fd2)