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 fromView on GitHub (pinned to 9b90983fd2)
Solutions
- Change the smallest stop to a positive double less than 1, e.g. 0.05 or 0.1.
- Remove the property to fall back to DEFAULT_FULLNESS_FACTORIZATION_STOPS.
- Fix the templating script that computed the stop value (avoid 0/NaN outputs).
- 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
- Keep all stops strictly inside (0,1)
- Reject 0/NaN/negative values in config templating
- Clamp generated stops with Math.max/min bounds
- Test flag parsing with a startup check script
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
- Last bitmapFullnessFactorizationStop[%d] should be < 1
- Empty bitmapFullnessFactorizationStops:
- Non unique bitmapFullnessFactorizationStops:
- Only positive integers or zero can be added
- Cannot remove non Integer from integer BitSet
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/a6f4600ca5fc3443.
Report an issue: GitHub.