apache/druid · error · IAE
Unknown type[%s] for metric[%s]
Error message
Unknown type[%s] for metric[%s]
What it means
LegacyTopNMetricSpec.getDimension converts the legacy topN 'metric' field into a dimension name string. It accepts either a plain String or a Map containing a 'metric' key; any other JSON shape (number, array, boolean, null-mapped object without the key handled elsewhere) hits the fallback IllegalArgumentException 'Unknown type[%s] for metric[%s]'. It exists because the legacy metric spec format is lenient but must ultimately resolve to a string.
Source
Thrown at processing/src/main/java/org/apache/druid/query/topn/LegacyTopNMetricSpec.java:40
import com.fasterxml.jackson.annotation.JsonCreator;
import org.apache.druid.java.util.common.IAE;
import java.util.Map;
/**
*/
public class LegacyTopNMetricSpec extends NumericTopNMetricSpec
{
private static String convertValue(Object metric)
{
final String retVal;
if (metric instanceof String) {
retVal = (String) metric;
} else if (metric instanceof Map) {
retVal = (String) ((Map) metric).get("metric");
} else {
throw new IAE("Unknown type[%s] for metric[%s]", metric.getClass(), metric);
}
return retVal;
}
@JsonCreator
public LegacyTopNMetricSpec(Object metric)
{
super(convertValue(metric));
}
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Change the query's topN 'metric' field to a plain string dimension name
- If using an object form, ensure it is {"type":"numeric","metric":"<name>"} or {"type":"lexicographic","metric":"<name>"} with a string 'metric' value
- Validate query JSON against the TopNQuery schema before submitting
- If building queries in code, pass String instead of raw numbers/objects for the metric
Example fix
// before
{"queryType":"topN","metric": 42, ...}
// after
{"queryType":"topN","metric":"visits", ...} Defensive patterns
Strategy: validation
Validate before calling
Object metric = queryJson.get("metric");
if (metric instanceof String) { /* ok */ }
else if (metric instanceof Map) {
Object m = ((Map<?, ?>) metric).get("metric");
if (!(m instanceof String)) throw new IllegalArgumentException("metric must resolve to a string");
} else {
throw new IllegalArgumentException("topN metric must be a string or a map with a string 'metric' key");
} Type guard
boolean isValidTopNMetric(Object metric) {
return metric instanceof String
|| (metric instanceof Map && ((Map<?, ?>) metric).get("metric") instanceof String);
} Prevention
- Always emit topN 'metric' as a string or {"type":...,"metric":"<string>"}
- Validate query JSON against the TopNQuery schema client-side before submission
- Use Druid's query JSON deserialization round-trip in tests to catch malformed metric specs
When it happens
Trigger: Calling convertValue (via LegacyDimensionSpec) with a topN metric field deserialized as a non-String, non-Map type, e.g. a numeric metric like "metric": 42, a list, or a JSON object missing the 'metric' key producing an unexpected shape in upstream deserialization.
Common situations: Hand-written native topN JSON queries where the metric was written as a number or nested array; clients generating query JSON programmatically with wrong types; queries migrated from older Druid versions where alternate metric encodings were tolerated.
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 operate on a dimension with no dictionary
- Cannot operate on a dimension with unknown cardinality
- Null cursor factory found. Probably trying to issue a query
- Query type '%s' does not support returning results as arrays
- Can't find the topN metric
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/375cc38c89f7d822.
Report an issue: GitHub.