apache/druid · critical · RE

First bitmapFullnessFactorizationStop[%d] should be > 0

Error message

First bitmapFullnessFactorizationStop[%d] should be > 0

What it means

After sorting the parsed bitmapFullnessFactorizationStops, BitmapOffset requires the smallest stop to be strictly greater than 0 (and not NaN). If the first stop is 0, negative, or NaN, the static initializer throws RE 'First bitmapFullnessFactorizationStop[%d] should be > 0'. Stops define bitmap-fullness factorization bands and 0 would produce a degenerate first band.

Source

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

    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);
    }

    String prevStop = "0";
    FACTORIZED_FULLNESS = new String[stopsArray.length + 1];
    for (int i = 0; i < stopsArray.length; i++) {
      String stop = String.valueOf(BITMAP_FULLNESS_FACTORIZATION_STOPS[i]);
      FACTORIZED_FULLNESS[i] = "(" + prevStop + ", " + stop + "]";
      prevStop = stop;
    }
    FACTORIZED_FULLNESS[stopsArray.length] = "(" + prevStop + ", 1)";
  }

  /**
   * Processing of queries with BitmapOffsets, whose Bitmaps has different factorized fullness (bucket), reported from

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Change the smallest stop to a positive double less than 1, e.g. 0.05 or 0.1.
  2. Remove the property to fall back to DEFAULT_FULLNESS_FACTORIZATION_STOPS.
  3. Fix the templating script that computed the stop value (avoid 0/NaN outputs).
  4. Restart the process; the validation occurs in the static initializer and fails JVM startup of that class.

Example fix

// before
-DbitmapFullnessFactorizationStops=0,0.5
// after
-DbitmapFullnessFactorizationStops=0.1,0.5
Defensive patterns

Strategy: validation

Validate before calling

double first = parsed[0]; // after sort
if (Double.isNaN(first) || first <= 0.0) {
  throw new IllegalStateException("first stop must be > 0");
}

Type guard

boolean validStops(List<Double> stops) {
  List<Double> s = new ArrayList<>(stops);
  Collections.sort(s);
  return !Double.isNaN(s.get(0)) && s.get(0) > 0.0;
}

Try / catch

try {
  validateStops(prop);
} catch (IllegalArgumentException e) {
  log.error(e, "bitmap stop out of range; using defaults");
  prop = DEFAULT_FULLNESS_FACTORIZATION_STOPS;
}

Prevention

When it happens

Trigger: Starting a JVM with -DbitmapFullnessFactorizationStops=0,... or with a negative/NaN first value after comma-split (e.g. '0,0.5' or 'NaN,0.5'); the check runs at class load after Arrays.sort.

Common situations: Ops writing 0 as the natural lower bound, assuming an inclusive range; NaN produced by a templating expression gone wrong; misconfigured tuning knobs copied from another system.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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