apache/druid · error · IllegalStateException

Unable to handle type

Error message

Unable to handle type[%s] for AggregatorFactory[%s]

What it means

IncrementalIndex's MetricDesc/MetricHolder capabilities logic only handles numeric and COMPLEX ValueTypes; anything else (e.g. STRING, arrays) for an AggregatorFactory's required type is rejected with this ISE. It marks an unsupported combination of aggregator output type and index capability handling.

Solutions

  1. Change the aggregator so its output type is numeric or a registered complex type
  2. For string outputs, use a dimension plus query-time aggregation instead of an ingestion-time metric
  3. Patch/extend IncrementalIndex capability handling if this is your own custom aggregator type

Example fix

// before: custom aggregator with typeName "string"
public String getTypeName() { return "string"; }
// after: return a complex or numeric type
public String getTypeName() { return "long"; }
Defensive patterns

Strategy: validation

Validate before calling

String t = factory.getTypeName();
if (!isNumeric(t) && !isComplex(t)) throw new IllegalArgumentException("Bad aggregator type: " + t);

Try / catch

try { index.add(row); } catch (ISE e) { if (e.getMessage().contains("Unable to handle type")) { /* fix aggregator */ } throw e; }

Prevention

When it happens

Trigger: Constructing an IncrementalIndex with an AggregatorFactory whose getTypeName()/required type resolves to a non-numeric, non-complex ValueType (STRING or ARRAY), e.g. a custom aggregator returning strings or a misconfigured spec.

Common situations: Custom AggregatorFactory implementations declaring string/array intermediate types; spec errors where a dimension-style aggregator is used in metricsSpec; upgrading Druid where new ValueTypes (arrays) exist but index support is absent.

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


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/cf8f5b6a2f4afd92. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndex.java:1048

        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()
    {
      return index;
    }

    public String getName()
    {
      return name;
    }

    public String getType()
    {
      return type;
    }

View on GitHub (pinned to 9b90983fd2)