{"record":{"id":"56e4ff96e23da62d","repo":"apache/druid","slug":"illegal-probability-s-must-be-strictly-between-56e4ff","errorCode":null,"errorMessage":"Illegal probability[%s], must be strictly between 0 and 1","messagePattern":"Illegal probability\\[(.+?)\\], must be strictly between 0 and 1","errorType":"validation","errorClass":"org.apache.druid.java.util.common.IAE","httpStatus":null,"severity":"error","filePath":"extensions-core/histogram/src/main/java/org/apache/druid/query/aggregation/histogram/QuantilesPostAggregator.java","lineNumber":57,"sourceCode":"\n@JsonTypeName(\"quantiles\")\npublic class QuantilesPostAggregator extends ApproximateHistogramPostAggregator\n{\n  private final float[] probabilities;\n\n  @JsonCreator\n  public QuantilesPostAggregator(\n      @JsonProperty(\"name\") String name,\n      @JsonProperty(\"fieldName\") String fieldName,\n      @JsonProperty(\"probabilities\") float[] probabilities\n  )\n  {\n    super(name, fieldName);\n    this.probabilities = probabilities;\n\n    for (float p : probabilities) {\n      if (p < 0 || p > 1) {\n        throw new IAE(\"Illegal probability[%s], must be strictly between 0 and 1\", p);\n      }\n    }\n  }\n\n  @Override\n  public Comparator getComparator()\n  {\n    throw new UnsupportedOperationException();\n  }\n\n  @Override\n  public Set<String> getDependentFields()\n  {\n    return Sets.newHashSet(fieldName);\n  }\n\n  @Override\n  public Object compute(Map<String, Object> values)","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/histogram/src/main/java/org/apache/druid/query/aggregation/histogram/QuantilesPostAggregator.java#L39-L75","documentation":"The QuantilesPostAggregator constructor validates each probability in the list is strictly between 0 and 1, throwing IllegalArgumentException for the first invalid one. Quantiles are undefined at 0 or 1, so the entire probability list must be within the open interval.","triggerScenarios":"Building QuantilesPostAggregator with a probabilities array containing any value <= 0 or >= 1, e.g. [0.25, 0.5, 1.0].","commonSituations":"Percentile lists converted from percent scale where 0 or 100 slipped through; user-supplied percentile config without validation; generated specs with float rounding pushing a value to exactly 1.0f.","solutions":["Validate/filter the probabilities array to values strictly between 0 and 1 before constructing.","Convert percent values with p/100 and reject 0% and 100% requests (use min/max post-aggs instead for extremes).","Clamp or drop boundary values in upstream configuration loading."],"exampleFix":"// before\n{\"type\": \"quantiles\", \"fieldName\": \"h\", \"probabilities\": [0.5, 1.0]}\n// after\n{\"type\": \"quantiles\", \"fieldName\": \"h\", \"probabilities\": [0.5, 0.99]}","handlingStrategy":"validation","validationCode":"for (float p : probabilities) {\n  if (!(p > 0 && p < 1)) {\n    throw new IllegalArgumentException(\"probability must be strictly between 0 and 1, got \" + p);\n  }\n}","typeGuard":"boolean allValidProbabilities(List<Float> ps) {\n  return ps.stream().allMatch(p -> p > 0f && p < 1f);\n}","tryCatchPattern":"try {\n  QuantilesPostAggregator q = new QuantilesPostAggregator(name, fieldName, probabilities);\n} catch (IllegalArgumentException e) {\n  // filter invalid probabilities and retry\n}","preventionTips":["Filter or reject probability arrays before constructing the post-aggregator.","Guard percent conversions so 0% and 100% never enter the list.","Watch float rounding: values like 0.9999999f in float precision may round toward 1.0f."],"tags":["druid","histogram","post-aggregator","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}