apache/druid · error · IllegalStateException
String is not a metric column type
Error message
String is not a metric column type
What it means
IncrementalIndex's metric column selector factory throws IllegalStateException('String is not a metric column type') when a column declared as a metric has STRING capabilities. Metrics must be numeric (long/float/double) or complex; a string-typed metric indicates the schema mislabels a dimension as a metric.
Source
Thrown at processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndex.java:793
String metric
)
{
final MetricDesc metricDesc = rowSelector.getMetric(metric);
if (metricDesc == null) {
return NilColumnValueSelector.instance();
}
int metricIndex = metricDesc.getIndex();
switch (metricDesc.getCapabilities().getType()) {
case COMPLEX:
return new ObjectMetricColumnSelector(rowSelector, currEntry, metricDesc);
case LONG:
return new LongMetricColumnSelector(rowSelector, currEntry, metricIndex);
case FLOAT:
return new FloatMetricColumnSelector(rowSelector, currEntry, metricIndex);
case DOUBLE:
return new DoubleMetricColumnSelector(rowSelector, currEntry, metricIndex);
case STRING:
throw new IllegalStateException("String is not a metric column type");
default:
throw new ISE("Unknown metric value type: %s", metricDesc.getCapabilities().getType());
}
}
public Interval getInterval()
{
DateTime min = DateTimes.utc(minTimestamp);
return new Interval(min, isEmpty() ? min : queryGranularity.increment(DateTimes.utc(getMaxTimeMillis())));
}
@Nullable
public DateTime getMinTime()
{
return isEmpty() ? null : DateTimes.utc(getMinTimeMillis());
}
@NullableView on GitHub (pinned to 9b90983fd2)
Solutions
- Remove the string column from metricsSpec or declare it in the dimensionsSpec instead
- Use a proper numeric/complex aggregator for metric columns
- Check capabilities: assert getType() != ValueType.STRING before treating a column as a metric
Example fix
// before
"metricsSpec": [{"type": "string", "name": "country"}] // invalid
// after
"metricsSpec": [{"type": "doubleSum", "name": "revenue", "fieldName": "revenue"}]
// and move "country" to dimensionsSpec Defensive patterns
Strategy: validation
Validate before calling
if (capabilities.getType() == ValueType.STRING) { throw new IllegalArgumentException("Column " + name + " is a dimension, not a metric"); } Try / catch
try { selector = index.makeColumnValueSelector(...); } catch (IllegalStateException e) { if (e.getMessage().contains("String is not a metric column type")) { throw new IllegalStateException("metricsSpec mislabels a string column as metric", e); } throw e; } Prevention
- Cross-check metricsSpec aggregator names against dimensionsSpec
- Ensure column capabilities are derived from the actual schema
- Validate ingestion specs before submission (schema linting)
When it happens
Trigger: Constructing or querying an IncrementalIndex whose metricsSpec includes a metric of type 'string', or where column capabilities resolve the metric column to STRING.
Common situations: ingestion spec metricsSpec listing a dimension (e.g. a string aggregator name) as a metric; schema/rollup mistakes after changing a column from dimension to metric; typos in aggregator type names causing fallback to string type.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- incrementIndexSchema cannot be null
- ColumnCapacityExceededException
- Cannot coerce column [%s] input to requested type [%s]
- Unhandled type: %s
- Column[%s] has conflicting types [%s] and [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/cc935bc878b65cc6.
Report an issue: GitHub.