{"record":{"id":"a6f4600ca5fc3443","repo":"apache/druid","slug":"first-bitmapfullnessfactorizationstop-d-should-b","errorCode":null,"errorMessage":"First bitmapFullnessFactorizationStop[%d] should be > 0","messagePattern":"First bitmapFullnessFactorizationStop\\[(.+?)\\] should be > 0","errorType":"validation","errorClass":"RE","httpStatus":null,"severity":"critical","filePath":"processing/src/main/java/org/apache/druid/segment/BitmapOffset.java","lineNumber":72,"sourceCode":"    String[] stopsArray = stopString.split(\",\");\n    if (stopsArray.length == 0) {\n      throw new RE(\"Empty bitmapFullnessFactorizationStops: \" + stopString);\n    }\n    if (new HashSet<>(Arrays.asList(stopsArray)).size() != stopsArray.length) {\n      throw new RE(\"Non unique bitmapFullnessFactorizationStops: \" + stopString);\n    }\n\n    BITMAP_FULLNESS_FACTORIZATION_STOPS = new double[stopsArray.length];\n    for (int i = 0; i < stopsArray.length; i++) {\n      String stop = stopsArray[i];\n      BITMAP_FULLNESS_FACTORIZATION_STOPS[i] = Double.parseDouble(stop);\n\n    }\n    Arrays.sort(BITMAP_FULLNESS_FACTORIZATION_STOPS);\n\n    double firstStop = BITMAP_FULLNESS_FACTORIZATION_STOPS[0];\n    if (Double.isNaN(firstStop) || firstStop <= 0.0) {\n      throw new RE(\"First bitmapFullnessFactorizationStop[%d] should be > 0\", firstStop);\n    }\n    double lastStop = BITMAP_FULLNESS_FACTORIZATION_STOPS[stopsArray.length - 1];\n    if (Double.isNaN(lastStop) || lastStop >= 1) {\n      throw new RE(\"Last bitmapFullnessFactorizationStop[%d] should be < 1\", lastStop);\n    }\n\n    String prevStop = \"0\";\n    FACTORIZED_FULLNESS = new String[stopsArray.length + 1];\n    for (int i = 0; i < stopsArray.length; i++) {\n      String stop = String.valueOf(BITMAP_FULLNESS_FACTORIZATION_STOPS[i]);\n      FACTORIZED_FULLNESS[i] = \"(\" + prevStop + \", \" + stop + \"]\";\n      prevStop = stop;\n    }\n    FACTORIZED_FULLNESS[stopsArray.length] = \"(\" + prevStop + \", 1)\";\n  }\n\n  /**\n   * Processing of queries with BitmapOffsets, whose Bitmaps has different factorized fullness (bucket), reported from","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/BitmapOffset.java#L54-L90","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n-DbitmapFullnessFactorizationStops=0,0.5\n// after\n-DbitmapFullnessFactorizationStops=0.1,0.5","handlingStrategy":"validation","validationCode":"double first = parsed[0]; // after sort\nif (Double.isNaN(first) || first <= 0.0) {\n  throw new IllegalStateException(\"first stop must be > 0\");\n}","typeGuard":"boolean validStops(List<Double> stops) {\n  List<Double> s = new ArrayList<>(stops);\n  Collections.sort(s);\n  return !Double.isNaN(s.get(0)) && s.get(0) > 0.0;\n}","tryCatchPattern":"try {\n  validateStops(prop);\n} catch (IllegalArgumentException e) {\n  log.error(e, \"bitmap stop out of range; using defaults\");\n  prop = DEFAULT_FULLNESS_FACTORIZATION_STOPS;\n}","preventionTips":["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"],"tags":["java","jvm-properties","static-init","bitmap","value-out-of-range"],"backgroundTag":"value-out-of-range","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}