apache/druid · error · IllegalStateException
Unable to handle complex type[%s]
Error message
Unable to handle complex type[%s]
What it means
When IncrementalIndex sets up column capabilities for an aggregator of COMPLEX ValueType, it looks up a ComplexMetricSerde by the complex type name. If none is registered (ComplexMetrics.getSerdeForType returns null) the index cannot serialize/handle that complex type and throws this ISE.
Source
Thrown at processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndex.java:1034
private final int index;
private final String name;
private final String type;
private final ColumnCapabilities capabilities;
public MetricDesc(int index, AggregatorFactory factory)
{
this.index = index;
this.name = factory.getName();
ColumnType valueType = factory.getIntermediateType();
if (valueType.isNumeric()) {
capabilities = ColumnCapabilitiesImpl.createSimpleNumericColumnCapabilities(valueType);
this.type = valueType.toString();
} else if (valueType.is(ValueType.COMPLEX)) {
ComplexMetricSerde serde = ComplexMetrics.getSerdeForType(valueType.getComplexTypeName());
if (serde == null) {
throw new ISE("Unable to handle complex type[%s]", valueType);
}
this.type = serde.getTypeName();
// The serde's type name represents the canonical storage type (e.g., "HLLSketch"),
// while the aggregator's intermediate type may be more specific (e.g., "HLLSketchBuild").
// Using the serde's type ensures that segment metadata queries return consistent types
// across realtime (IncrementalIndex) and historical (QueryableIndex) segments.
// See https://github.com/apache/druid/issues/14315.
capabilities = ColumnCapabilitiesImpl.createDefault()
.setType(ColumnType.ofComplex(serde.getTypeName()))
.setHasNulls(ColumnCapabilities.Capable.TRUE);
} else {
// if we need to handle non-numeric and non-complex types (e.g. strings, arrays) it should be done here
// and we should determine the appropriate ColumnCapabilities
throw new ISE("Unable to handle type[%s] for AggregatorFactory[%s]", valueType, factory.getClass());
}
}
public int getIndex()View on GitHub (pinned to 9b90983fd2)
Solutions
- Load the extension providing the serde (e.g. druid-datasketches) via druid.extensions.loadList on the server running the task
- Verify ComplexMetrics registry contains the type (check extension was bundled into the task classpath)
- Correct the aggregator/typeName spelling so it matches a registered serde
Example fix
// before (server not loading sketch extension) "druid.extensions.loadList": ["druid-kafka-indexing-service"] // after "druid.extensions.loadList": ["druid-kafka-indexing-service", "druid-datasketches"]
Defensive patterns
Strategy: validation
Validate before calling
if (ComplexMetrics.getSerdeForType(typeName) == null) {
throw new IllegalStateException("No serde for " + typeName + "; check druid.extensions.loadList");
} Try / catch
try { initIndex(); } catch (ISE e) { if (e.getMessage().startsWith("Unable to handle complex type")) { /* load missing extension */ } throw e; } Prevention
- List all sketch extensions in druid.extensions.loadList
- Mirror extension config between test and production
When it happens
Trigger: Creating an IncrementalIndex with an AggregatorFactory whose required type is COMPLEX (e.g. sketch aggregators) while no serde is registered for that complex type name, typically because the extension providing the serde is not loaded.
Common situations: Using datasketches/HLL/streaming-aggregation aggregators without loading the corresponding Druid extension on the ingestion/peon server; typo'd complex type names.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- No serde for complexTypeName[%s]
- extractValue without an aggregator factory is not supported.
- Unknown type:
- No complexTypeName, cannot write column [%s]
- No serde for complexTypeName[%s], cannot write column [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/40ad289f65756f35.
Report an issue: GitHub.