apache/druid · error · org.apache.druid.java.util.common.parsers.ParseException
Unknown type[%s] for field[%s]
Error message
Unknown type[%s] for field[%s]
What it means
objectToNumber handles null, Number, and String inputs; anything else (e.g. a Map, List, byte[], or complex object) is not convertible to a number, so with throwParseExceptions=true it throws a ParseException reporting the value's Java class and field name. This catches structural mismatches where a field holds a non-scalar value where a number was expected.
Source
Thrown at processing/src/main/java/org/apache/druid/data/input/Rows.java:166
asNumber = v;
}
catch (Exception e) {
if (throwParseExceptions) {
throw new ParseException(
String.valueOf(inputValue),
e,
"Unable to parse value[%s] for field[%s]",
inputValue,
name
);
} else {
return null;
}
}
} else {
if (throwParseExceptions) {
throw new ParseException(
String.valueOf(inputValue),
"Unknown type[%s] for field[%s]",
inputValue.getClass(),
name
);
} else {
return null;
}
}
if (outputType == null || asNumber == null) {
return asNumber;
} else if (outputType == ValueType.LONG) {
return asNumber.longValue();
} else if (outputType == ValueType.FLOAT) {
return asNumber.floatValue();
} else if (outputType == ValueType.DOUBLE) {
return asNumber.doubleValue();View on GitHub (pinned to 9b90983fd2)
Solutions
- Add a flattenSpec/transform so the field is extracted to a scalar string or number before numeric conversion.
- Convert the value upstream (e.g. parse timestamps to millis longs) before passing to objectToNumber.
- Set throwParseExceptions=false to skip unconvertible values (returns null).
- Correct the column's type spec so non-numeric fields are not treated as metrics.
Example fix
// before
Number n = Rows.objectToNumber("tags", Collections.singletonList("a"), true);
// after
Number n = Rows.objectToNumber("tags_count", ((List<?>) value).size(), true); Defensive patterns
Strategy: type-guard
Validate before calling
boolean isScalarNumericCandidate(Object v) {
return v == null || v instanceof Number || v instanceof String;
} Type guard
Number toNumberSafe(Object v) {
if (v instanceof Number) return (Number) v;
if (v instanceof String) return Rows.objectToNumber("f", v, false);
return null; // maps, lists, byte[] are not numeric
} Try / catch
try {
return Rows.objectToNumber(field, value, true);
} catch (ParseException e) {
if (e.getMessage() != null && e.getMessage().contains("Unknown type")) {
log.warn("Field %s holds a non-scalar value of class %s", field, value.getClass());
return null;
}
throw e;
} Prevention
- Verify with a flattenSpec that nested JSON fields are flattened to scalars before mapping to metrics.
- Check the actual Java/JSON class of ingestion fields during parser development.
- Never feed arrays, maps, or byte[] into numeric aggregation paths.
- Add a transform to convert complex values (e.g. timestamps) to numbers first.
When it happens
Trigger: Passing a non-scalar input (nested JSON object/array, byte[], Timestamp object) as inputValue to Rows.objectToNumber with throwParseExceptions=true; ingestion mappings where a nested/complex field is wired into a numeric metric.
Common situations: JSON ingestion where the metric column is actually a nested object; flattenSpec producing arrays where scalars were expected; timestamp objects routed into numeric aggregators instead of being converted first.
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
- Output type[%s] must be numeric
- Unable to parse value[%s] for field[%s]
- Cannot deserialize type[%s] to an RoaringBitmap64Counter:
- Object cannot be deserialized to a Spectator Histogram
- Expected a number or an instance of MergingDigest, but recei
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/1c2840455f3230c1.
Report an issue: GitHub.