apache/druid · critical · RE

Non unique bitmapFullnessFactorizationStops:

Error message

Non unique bitmapFullnessFactorizationStops: 

What it means

The static initializer of BitmapOffset validates that the comma-separated bitmapFullnessFactorizationStops system property contains unique values. If the parsed stop list has duplicates (set size differs from array length), it throws RE 'Non unique bitmapFullnessFactorizationStops: ' echoing the raw string. This happens once per JVM at class initialization.

Source

Thrown at processing/src/main/java/org/apache/druid/segment/BitmapOffset.java:59

  private static final int INVALID_VALUE = -1;

  /**
   * Currently the default stops are not consciously optimized for the goals described in {@link #factorizeFullness}.
   * They are chosen intuitively. There was no experimentation with different bitmapFullnessFactorizationStops.
   * Experimentation and performance feedback with a different set of stops is welcome.
   */
  private static final String DEFAULT_FULLNESS_FACTORIZATION_STOPS = "0.01,0.1,0.3,0.5,0.7,0.9,0.99";
  private static final double[] BITMAP_FULLNESS_FACTORIZATION_STOPS;
  private static final String[] FACTORIZED_FULLNESS;

  static {
    String stopString = System.getProperty("bitmapFullnessFactorizationStops", DEFAULT_FULLNESS_FACTORIZATION_STOPS);
    String[] stopsArray = stopString.split(",");
    if (stopsArray.length == 0) {
      throw new RE("Empty bitmapFullnessFactorizationStops: " + stopString);
    }
    if (new HashSet<>(Arrays.asList(stopsArray)).size() != stopsArray.length) {
      throw new RE("Non unique bitmapFullnessFactorizationStops: " + stopString);
    }

    BITMAP_FULLNESS_FACTORIZATION_STOPS = new double[stopsArray.length];
    for (int i = 0; i < stopsArray.length; i++) {
      String stop = stopsArray[i];
      BITMAP_FULLNESS_FACTORIZATION_STOPS[i] = Double.parseDouble(stop);

    }
    Arrays.sort(BITMAP_FULLNESS_FACTORIZATION_STOPS);

    double firstStop = BITMAP_FULLNESS_FACTORIZATION_STOPS[0];
    if (Double.isNaN(firstStop) || firstStop <= 0.0) {
      throw new RE("First bitmapFullnessFactorizationStop[%d] should be > 0", firstStop);
    }
    double lastStop = BITMAP_FULLNESS_FACTORIZATION_STOPS[stopsArray.length - 1];
    if (Double.isNaN(lastStop) || lastStop >= 1) {
      throw new RE("Last bitmapFullnessFactorizationStop[%d] should be < 1", lastStop);
    }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Edit jvm.config to remove the duplicated stop so all values are distinct.
  2. Use the default by deleting the -DbitmapFullnessFactorizationStops flag.
  3. Deduplicate the generated list in the config script (e.g. sort -u) before injecting it into JVM args.
  4. Restart the service after the fix; the exception aborts class loading.

Example fix

// before
-DbitmapFullnessFactorizationStops=0.2,0.5,0.2
// after
-DbitmapFullnessFactorizationStops=0.2,0.5,0.8
Defensive patterns

Strategy: validation

Validate before calling

String[] stops = prop.split(",");
if (new HashSet<>(Arrays.asList(stops)).size() != stops.length) {
  throw new IllegalStateException("duplicate bitmapFullnessFactorizationStops");
}

Type guard

boolean uniqueStops(String prop) {
  String[] s = prop.split(",");
  return new HashSet<>(Arrays.asList(s)).size() == s.length;
}

Try / catch

try {
  config.validateBitmapStops();
} catch (RuntimeException e) {
  log.error(e, "invalid bitmapFullnessFactorizationStops, falling back to default");
}

Prevention

When it happens

Trigger: Launching a Druid process with -DbitmapFullnessFactorizationStops containing a repeated value, e.g. '0.2,0.5,0.2' — detected by comparing HashSet size to array length in the static block.

Common situations: Hand-edited jvm.config tuning values that duplicate a stop; scripted config generation appending a default stop that already exists in a custom list; typo'd copies of the default stop list.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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