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
FrontCodedIndexedWriter's constructor validates that bucketSize is a power of two between 1 and 128 inclusive. Power-of-two bucket sizes are required for the bit-shift based indexing, and the 1..128 cap bounds memory (bucketBuffer and scratch sizing). Invalid values throw IAE before any writing happens.
Solutions
- Set bucketSize to a power of two between 1 and 128 (the default is 4)
- Validate user config before passing it to the writer: (bucketSize & (bucketSize - 1)) == 0 && bucketSize >= 1 && bucketSize <= 128
- Use FrontCodedIndexed.write() helpers or config parsing that clamps/validates the bucket size automatically
- If coming from SQL/ingestion spec, correct the 'compressionFormat': 'frontCoded' with a legal bucketSize parameter
Example fix
// before int bucketSize = 5; new FrontCodedIndexedWriter<>(medium, ordering, byteOrder, bucketSize, version); // IAE // after int bucketSize = 8; // power of two, 1..128 new FrontCodedIndexedWriter<>(medium, ordering, byteOrder, bucketSize, version);
Defensive patterns
Strategy: validation
Validate before calling
boolean validBucketSize(int n) {
return n >= 1 && n <= 128 && Integer.bitCount(n) == 1;
}
// call before constructing: if (!validBucketSize(bucketSize)) fail fast Try / catch
try {
writer = new FrontCodedIndexedWriter<>(medium, ordering, byteOrder, bucketSize, version);
} catch (IllegalArgumentException e) {
// fall back to DEFAULT_BUCKET_SIZE (4) or reject the config
} Prevention
- Validate user-supplied bucketSize configs at config-parse time
- Stick to powers of two: 1, 2, 4, 8, ..., 128; default 4 is safe
- Clamp or reject non-power-of-two values before they reach the writer
- Document the 1..128 power-of-two constraint wherever bucketSize is exposed
When it happens
Trigger: Constructing FrontCodedIndexedWriter with bucketSize values like 0, 3, 5, 6, or 256 — i.e. any value failing Integer.bitCount(bucketSize) == 1 || bucketSize < 1 || bucketSize > 128. This typically comes from a user-supplied frontCoded bucketSize config (e.g. SQL dictionary compression config) that was not validated.
Common situations: Setting the front-coded dictionary compression bucket size in ingestion/SQL configs to a non-power-of-two like 5 or 10; copy-paste of an example bucketSize; assuming any positive size is allowed.
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
- At least one of baseDir or files should be specified
- bucketSize must be a power of two but was[%,d]
- bucketSize must be a power of two but was[%,d]
- Cannot have a null/empty columns
- Cannot set kafka property [auto.offset.reset]. Property…
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/f4266015f1d57161.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/data/FrontCodedIndexedWriter.java:86
private WriteOutBytes headerOut = null;
@Nullable
private WriteOutBytes valuesOut = null;
private int numWritten = 0;
private ByteBuffer scratch;
private int logScratchSize = 10;
private boolean isClosed = false;
private boolean hasNulls = false;
public FrontCodedIndexedWriter(
SegmentWriteOutMedium segmentWriteOutMedium,
ByteOrder byteOrder,
int bucketSize,
byte version
)
{
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 byte[bucketSize][];
this.getOffsetBuffer = ByteBuffer.allocate(Integer.BYTES).order(byteOrder);
this.div = Integer.numberOfTrailingZeros(bucketSize);
this.version = FrontCodedIndexed.validateVersion(version);
}
@Override
public void open() throws IOException
{
headerOut = segmentWriteOutMedium.makeWriteOutBytes();
valuesOut = segmentWriteOutMedium.makeWriteOutBytes();
}
View on GitHub (pinned to 9b90983fd2)