{"record":{"id":"13dfb37a3faff382","repo":"apache/druid","slug":"comparing-arrays-of-estimates-and-error-bounds-is","errorCode":null,"errorMessage":"Comparing arrays of estimates and error bounds is not supported","messagePattern":"Comparing arrays of estimates and error bounds is not supported","errorType":"exception","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/hll/HllSketchToEstimateWithBoundsPostAggregator.java","lineNumber":100,"sourceCode":"    return field;\n  }\n\n  @JsonProperty\n  public int getNumStdDev()\n  {\n    return numStdDevs;\n  }\n\n  @Override\n  public Set<String> getDependentFields()\n  {\n    return field.getDependentFields();\n  }\n\n  @Override\n  public Comparator<double[]> getComparator()\n  {\n    throw new IAE(\"Comparing arrays of estimates and error bounds is not supported\");\n  }\n\n  @Override\n  public double[] compute(final Map<String, Object> combinedAggregators)\n  {\n    Object hllSketchHolderObject = field.compute(combinedAggregators);\n    if (hllSketchHolderObject == null) {\n      return new double[] {0.0D, 0.0D, 0.0D};\n    }\n    final HllSketchHolder sketch = HllSketchHolder.fromObj(hllSketchHolderObject);\n    return new double[] {sketch.getEstimate(), sketch.getLowerBound(numStdDevs), sketch.getUpperBound(numStdDevs)};\n  }\n\n  @Override\n  public PostAggregator decorate(final Map<String, AggregatorFactory> aggregators)\n  {\n    return this;\n  }","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/hll/HllSketchToEstimateWithBoundsPostAggregator.java#L82-L118","documentation":"HllSketchToEstimateWithBoundsPostAggregator outputs double[] (estimate plus upper/lower bounds), and since arrays of estimates+bounds have no meaningful ordering, getComparator() always throws IllegalArgumentException. This post-aggregator cannot be used where comparability is required, e.g. as the field of an orderBy/sorting or comparator-consuming aggregator.","triggerScenarios":"Using HllSketchToEstimateWithBounds (estimate+bounds output) inside an ORDER BY / having spec, or feeding it into another post-aggregator that calls getComparator() (e.g. arithmetic or comparative post-aggs).","commonSituations":"Users trying to sort query results by estimate-with-bounds; wrapping the bounds post-agg in a greatest/least or comparison post-aggregator; streaming frameworks requesting a comparator for the post-aggregated column.","solutions":["Use HllSketchToEstimatePostAggregator (double estimate) where sorting/comparison is needed","Sort by a scalar projection (the estimate) rather than the double[] bounds array","If bounds are needed, output them as separate columns and sort by the estimate column"],"exampleFix":"// before\npostAggs.add(new HllSketchToEstimateWithBoundsPostAggregator(\"est\", field, 2));\nquery.orderBy(\"est\")\n// after\npostAggs.add(new HllSketchToEstimatePostAggregator(\"est\", field));\nquery.orderBy(\"est\")","handlingStrategy":"validation","validationCode":"if (postAgg instanceof HllSketchToEstimateWithBoundsPostAggregator) { throw new IllegalArgumentException(\"estimate-with-bounds output is not comparable; use HllSketchToEstimatePostAggregator for sorting\"); }","typeGuard":null,"tryCatchPattern":"try { cmp = postAgg.getComparator(); } catch (IllegalArgumentException e) { cmp = Comparator.comparingDouble(a -> ((double[]) a)[0]); } // compare by estimate only","preventionTips":["Never place estimate-with-bounds post-aggs in orderBy/having","Use HllSketchToEstimatePostAggregator for comparable output","Treat double[] bounds as display-only data"],"tags":["unsupported-operation","post-aggregator","datasketches","comparator"],"backgroundTag":"operation-not-supported","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"}