apache/druid · critical · RE
Last bitmapFullnessFactorizationStop[%d] should be < 1
Error message
Last bitmapFullnessFactorizationStop[%d] should be < 1
What it means
BitmapOffset also validates that the largest bitmapFullnessFactorizationStops value is strictly less than 1 (and not NaN), because a fullness stop of 1 or more would create an unbounded/degenerate factorization band. Violations throw RE 'Last bitmapFullnessFactorizationStop[%d] should be < 1' from the static initializer.
Source
Thrown at processing/src/main/java/org/apache/druid/segment/BitmapOffset.java:76
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
* this method, uses different copies of the same code, so JIT compiler analyzes and compiles the code for different
* factorized fullness separately. The goal is to capture frequency of abstraction usage in compressed bitmap
* algorithms, i. e.
* - "Zero sequence" vs. "Literal" vs. "One sequence" in {@link org.apache.druid.extendedset.intset.ImmutableConciseSet}View on GitHub (pinned to 9b90983fd2)
Solutions
- Change the largest stop to a double strictly below 1, e.g. 0.9 or 0.99.
- Remove the -DbitmapFullnessFactorizationStops flag to use the built-in defaults.
- Fix config generation to clamp stops to (0,1) exclusive.
- Restart after correcting; failure occurs during class initialization.
Example fix
// before -DbitmapFullnessFactorizationStops=0.2,1.0 // after -DbitmapFullnessFactorizationStops=0.2,0.9
Defensive patterns
Strategy: validation
Validate before calling
double last = parsed[parsed.length - 1]; // after sort
if (Double.isNaN(last) || last >= 1.0) {
throw new IllegalStateException("last stop must be < 1");
} Type guard
boolean validLastStop(List<Double> stops) {
List<Double> s = new ArrayList<>(stops);
Collections.sort(s);
return !Double.isNaN(s.get(s.size() - 1)) && s.get(s.size() - 1) < 1.0;
} Try / catch
try {
validateStops(prop);
} catch (IllegalArgumentException e) {
log.error(e, "bitmap stop >= 1 rejected; using defaults");
prop = DEFAULT_FULLNESS_FACTORIZATION_STOPS;
} Prevention
- Treat the stop range as open interval (0,1), never inclusive of 1
- Clamp generated stops to e.g. [0.01, 0.99]
- Guard templates against producing Infinity/NaN
- Validate all JVM tuning flags in CI startup checks
When it happens
Trigger: Starting a JVM with -DbitmapFullnessFactorizationStops containing a value >= 1 or NaN as the largest entry, e.g. '0.2,1.0' or '0.2,Infinity'; checked after sorting in the static block.
Common situations: Ops assuming the range is [0,1] inclusive and setting 1.0 as the last stop; Infinity or NaN leaking from generated config; adapting stop lists from other tuning systems with different ranges.
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
- First bitmapFullnessFactorizationStop[%d] should be > 0
- 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/23437606292f3ac4.
Report an issue: GitHub.