apache/druid · error · org.apache.druid.java.util.common.IAE
Incompatible type for metric[%s], expected a ApproximateHist
Error message
Incompatible type for metric[%s], expected a ApproximateHistogram, got a %s
What it means
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.
Source
Thrown at extensions-core/histogram/src/main/java/org/apache/druid/query/aggregation/histogram/ApproximateHistogramFoldingAggregatorFactory.java:77
}
@Override
public Aggregator factorize(ColumnSelectorFactory metricFactory)
{
@SuppressWarnings("unchecked")
ColumnValueSelector<ApproximateHistogram> selector = metricFactory.makeColumnValueSelector(fieldName);
final Class cls = selector.classOfObject();
if (cls.equals(Object.class) || ApproximateHistogram.class.isAssignableFrom(cls)) {
return new ApproximateHistogramFoldingAggregator(
selector,
resolution,
lowerLimit,
upperLimit
);
}
throw new IAE(
"Incompatible type for metric[%s], expected a ApproximateHistogram, got a %s",
fieldName,
cls
);
}
@Override
public BufferAggregator factorizeBuffered(ColumnSelectorFactory metricFactory)
{
@SuppressWarnings("unchecked")
ColumnValueSelector<ApproximateHistogram> selector = metricFactory.makeColumnValueSelector(fieldName);
final Class cls = selector.classOfObject();
if (cls.equals(Object.class) || ApproximateHistogram.class.isAssignableFrom(cls)) {
return new ApproximateHistogramFoldingBufferAggregator(selector, resolution, lowerLimit, upperLimit);
}
throw new IAE(View on GitHub (pinned to 9b90983fd2)
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.
Example fix
// before (query JSON)
{"type": "approxHistogramFold", "fieldName": "response_time_ms"}
// after: response_time_ms is numeric; aggregate it numerically or fold a real histogram column
{"type": "doubleSum", "fieldName": "response_time_ms"} Defensive patterns
Strategy: validation
Validate before calling
// Validate the column type before issuing an approxHistogramFold query:
// Confirm the segment column holds ApproximateHistogram objects, e.g. via SegmentMetadataQuery:
// column type check: col.getCapabilities("histField").getType() matches the expected histogram storage
// Only then build: {"type":"approxHistogramFold","fieldName":"histField"} Type guard
boolean isHistogramColumn(ColumnCapabilities caps) {
return caps != null && caps.getType() == ValueType.COMPLEX;
} Try / catch
try {
Aggregator agg = factory.factorize(selector);
agg.aggregate();
} catch (IllegalArgumentException e) {
// message names expected vs actual class; fix fieldName or switch aggregator
log.error("Column type incompatible with approxHistogramFold: {}", e.getMessage());
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot deserialize type[%s] to an RoaringBitmap64Counter:
- Expected a number or an instance of MergingDigest, but recei
- Must have a valid, non-null aggregator name
- Parameter fieldName must be specified
- AggregatorFactoryNotMergeableException(this, other)
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/9f986e7fae3e2529.
Report an issue: GitHub.