{"record":{"id":"9f986e7fae3e2529","repo":"apache/druid","slug":"incompatible-type-for-metric-s-expected-a-appro","errorCode":null,"errorMessage":"Incompatible type for metric[%s], expected a ApproximateHistogram, got a %s","messagePattern":"Incompatible type for metric\\[(.+?)\\], expected a ApproximateHistogram, got a (.+?)","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/ApproximateHistogramFoldingAggregatorFactory.java","lineNumber":77,"sourceCode":"  }\n\n  @Override\n  public Aggregator factorize(ColumnSelectorFactory metricFactory)\n  {\n    @SuppressWarnings(\"unchecked\")\n    ColumnValueSelector<ApproximateHistogram> selector = metricFactory.makeColumnValueSelector(fieldName);\n\n    final Class cls = selector.classOfObject();\n    if (cls.equals(Object.class) || ApproximateHistogram.class.isAssignableFrom(cls)) {\n      return new ApproximateHistogramFoldingAggregator(\n          selector,\n          resolution,\n          lowerLimit,\n          upperLimit\n      );\n    }\n\n    throw new IAE(\n        \"Incompatible type for metric[%s], expected a ApproximateHistogram, got a %s\",\n        fieldName,\n        cls\n    );\n  }\n\n  @Override\n  public BufferAggregator factorizeBuffered(ColumnSelectorFactory metricFactory)\n  {\n    @SuppressWarnings(\"unchecked\")\n    ColumnValueSelector<ApproximateHistogram> selector = metricFactory.makeColumnValueSelector(fieldName);\n\n    final Class cls = selector.classOfObject();\n    if (cls.equals(Object.class) || ApproximateHistogram.class.isAssignableFrom(cls)) {\n      return new ApproximateHistogramFoldingBufferAggregator(selector, resolution, lowerLimit, upperLimit);\n    }\n\n    throw new IAE(","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/histogram/src/main/java/org/apache/druid/query/aggregation/histogram/ApproximateHistogramFoldingAggregatorFactory.java#L59-L95","documentation":"ApproximateHistogramFoldingAggregatorFactory.factorize() validates that the column selector's underlying object type is compatible with ApproximateHistogram (either plain Object during ingestion or an ApproximateHistogram subclass). If the resolved class is some other concrete type, it throws IllegalArgumentException stating the expected and actual types. This prevents silently folding incompatible objects into histograms.","triggerScenarios":"Creating an approxHistogramFold aggregator against a column whose values are not ApproximateHistogram instances (e.g. a string, long, or other complex-typed column); selector.classOfObject() returns a non-histogram class during factorize.","commonSituations":"Pointing the aggregator at the wrong metric/field name in the query; schema changes where a column formerly holding histograms now holds scalars; typos in fieldName causing the wrong column to be selected; ingesting histograms with a different serializer class.","solutions":["Check the fieldName in the query JSON points at a column that actually contains ApproximateHistogram objects (typically produced by ingestion with approxHistogram rollup or approxHistogramFold).","Inspect the segment schema / column type to confirm the underlying class; adjust the query to match.","If the column is numeric, use a numeric aggregator (doubleSum, etc.) instead of approxHistogramFold.","Re-ingest the data with histogram aggregation enabled if histograms were never produced."],"exampleFix":"// before (query JSON)\n{\"type\": \"approxHistogramFold\", \"fieldName\": \"response_time_ms\"}\n// after: response_time_ms is numeric; aggregate it numerically or fold a real histogram column\n{\"type\": \"doubleSum\", \"fieldName\": \"response_time_ms\"}","handlingStrategy":"validation","validationCode":"// Validate the column type before issuing an approxHistogramFold query:\n// Confirm the segment column holds ApproximateHistogram objects, e.g. via SegmentMetadataQuery:\n// column type check: col.getCapabilities(\"histField\").getType() matches the expected histogram storage\n// Only then build: {\"type\":\"approxHistogramFold\",\"fieldName\":\"histField\"}","typeGuard":"boolean isHistogramColumn(ColumnCapabilities caps) {\n  return caps != null && caps.getType() == ValueType.COMPLEX;\n}","tryCatchPattern":"try {\n  Aggregator agg = factory.factorize(selector);\n  agg.aggregate();\n} catch (IllegalArgumentException e) {\n  // message names expected vs actual class; fix fieldName or switch aggregator\n  log.error(\"Column type incompatible with approxHistogramFold: {}\", e.getMessage());\n}","preventionTips":["Verify fieldName points at a column populated by approxHistogram ingestion/rollup.","Run a SegmentMetadataQuery to inspect column types before writing histogram queries.","Use a numeric aggregator when the column stores plain numbers.","Watch for schema migrations that replace histogram columns with scalar metrics."],"tags":["java","druid","aggregation","type-mismatch"],"backgroundTag":"type-mismatch","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"}