{"record":{"id":"7345d11fbed0ae24","repo":"apache/druid","slug":"bucketsize-must-be-a-power-of-two-but-was-d-7345d1","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/FrontCodedIndexed.java","lineNumber":154,"sourceCode":"  protected final int numBuckets;\n  protected final int div;\n  protected final int rem;\n  protected final int offsetsPosition;\n  protected final int bucketsPosition;\n  protected final boolean hasNull;\n  protected final int lastBucketNumValues;\n\n  private FrontCodedIndexed(\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  }\n\n  /**\n   * Get a value from a bucket at a relative position.\n   * <p>","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/data/FrontCodedIndexed.java#L136-L172","documentation":"The FrontCodedIndexed reader constructor requires bucketSize to be a power of two (exactly one bit set) because the implementation uses bit tricks and bucket-relative offset math that only works for power-of-two buckets. A non-power-of-two value read from the header indicates corruption or a foreign format, so it throws ISE.","triggerScenarios":"Reading a FrontCodedIndexed whose serialized header contains a bucketSize with more than one bit set (e.g. 3, 5, 6) — caused by a corrupted segment buffer, reading at the wrong offset, or byte-order mismatch shifting fields.","commonSituations":"Corrupted or hand-edited segment files; reading a buffer from the wrong position so unrelated bytes are interpreted as bucketSize; writers from incompatible versions; custom code constructing FrontCodedIndexed directly with a bad bucketSize.","solutions":["Check the segment file for corruption and reload the segment from a backup or re-ingest the data","Verify the buffer position/byte order before constructing the reader — the header fields must be read in the writer's order","Do not construct FrontCodedIndexed directly; use the standard read() factory which reads valid headers","If your writer code produces the bucketSize, ensure it was validated as a power of two at write time (FrontCodedIndexedWriter enforces this)"],"exampleFix":"// before\nnew FrontCodedIndexed<>(buffer, order, 6, numValues, hasNull, offsetsPosition); // ISE\n// after\nint bucketSize = 4; // power of two, matching what the writer used\nnew FrontCodedIndexed<>(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  FrontCodedIndexed<String> idx = FrontCodedIndexed.read(buffer, order);\n} catch (IllegalStateException e) {\n  // corrupted header; reload or re-ingest the segment\n}","preventionTips":["Always deserialize with the standard read() factory rather than direct construction","Verify buffer position and ByteOrder before parsing headers","Validate power-of-two bucketSize at write time (the writer already does)","Re-ingest from source if a segment shows corruption"],"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"}