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
- Set bucketSize to a power of two in [1,128]: 1, 2, 4, 8, ..., 128 (e.g. 128).
- Round user config to the nearest valid power of two before constructing: bucketSize = Integer.highestOneBit(Math.max(1, Math.min(raw, 128))).
- 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
- Always derive bucketSize via Integer.highestOneBit / nextPowerOfTwo helpers
- Validate user config at parse time, before writer construction
- Keep allowed constants (1,2,4,...,128) in an enum or whitelist
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
- bucketSize must be a power of two but was[%,d]
- Detected conflicting prefixes in join clauses
- Detected duplicate prefix in join clauses
- maxStringBytes must be greater than 0
- maxStringBytes must be greater than 0
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();
}
@OverrideView on GitHub (pinned to 9b90983fd2)