{"record":{"id":"40ad289f65756f35","repo":"apache/druid","slug":"unable-to-handle-complex-type-s","errorCode":null,"errorMessage":"Unable to handle complex type[%s]","messagePattern":"Unable to handle complex type\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndex.java","lineNumber":1034,"sourceCode":"    private final int index;\n    private final String name;\n    private final String type;\n    private final ColumnCapabilities capabilities;\n\n    public MetricDesc(int index, AggregatorFactory factory)\n    {\n      this.index = index;\n      this.name = factory.getName();\n\n      ColumnType valueType = factory.getIntermediateType();\n\n      if (valueType.isNumeric()) {\n        capabilities = ColumnCapabilitiesImpl.createSimpleNumericColumnCapabilities(valueType);\n        this.type = valueType.toString();\n      } else if (valueType.is(ValueType.COMPLEX)) {\n        ComplexMetricSerde serde = ComplexMetrics.getSerdeForType(valueType.getComplexTypeName());\n        if (serde == null) {\n          throw new ISE(\"Unable to handle complex type[%s]\", valueType);\n        }\n        this.type = serde.getTypeName();\n        // The serde's type name represents the canonical storage type (e.g., \"HLLSketch\"),\n        // while the aggregator's intermediate type may be more specific (e.g., \"HLLSketchBuild\").\n        // Using the serde's type ensures that segment metadata queries return consistent types\n        // across realtime (IncrementalIndex) and historical (QueryableIndex) segments.\n        // See https://github.com/apache/druid/issues/14315.\n        capabilities = ColumnCapabilitiesImpl.createDefault()\n                                             .setType(ColumnType.ofComplex(serde.getTypeName()))\n                                             .setHasNulls(ColumnCapabilities.Capable.TRUE);\n      } else {\n        // if we need to handle non-numeric and non-complex types (e.g. strings, arrays) it should be done here\n        // and we should determine the appropriate ColumnCapabilities\n        throw new ISE(\"Unable to handle type[%s] for AggregatorFactory[%s]\", valueType, factory.getClass());\n      }\n    }\n\n    public int getIndex()","sourceCodeStart":1016,"sourceCodeEnd":1052,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndex.java#L1016-L1052","documentation":"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.","triggerScenarios":"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.","commonSituations":"Using datasketches/HLL/streaming-aggregation aggregators without loading the corresponding Druid extension on the ingestion/peon server; typo'd complex type names.","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"],"exampleFix":"// before (server not loading sketch extension)\n\"druid.extensions.loadList\": [\"druid-kafka-indexing-service\"]\n// after\n\"druid.extensions.loadList\": [\"druid-kafka-indexing-service\", \"druid-datasketches\"]","handlingStrategy":"validation","validationCode":"if (ComplexMetrics.getSerdeForType(typeName) == null) {\n  throw new IllegalStateException(\"No serde for \" + typeName + \"; check druid.extensions.loadList\");\n}","typeGuard":null,"tryCatchPattern":"try { initIndex(); } catch (ISE e) { if (e.getMessage().startsWith(\"Unable to handle complex type\")) { /* load missing extension */ } throw e; }","preventionTips":["List all sketch extensions in druid.extensions.loadList","Mirror extension config between test and production"],"tags":["extensions","complex-metric","serde"],"backgroundTag":"missing-dependency","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"}