apache/druid · error · IllegalArgumentException
Output type[%s] must be numeric
Error message
Output type[%s] must be numeric
What it means
Rows.objectToNumber validates that the requested outputType is a numeric ValueType (LONG, FLOAT, DOUBLE) before converting a field value to a Number. Druid throws this IllegalArgumentException immediately when a caller passes a non-numeric output type such as STRING or COMPLEX, because the method's contract is to produce numbers only. It is a programming/API misuse error, not a data error.
Source
Thrown at processing/src/main/java/org/apache/druid/data/input/Rows.java:122
* @param inputValue the actual object being converted
* @param outputType expected return type, or null if it should be automatically detected
* @param throwParseExceptions whether this method should throw a {@link ParseException} or use a default/null value
* when {@param inputValue} is not numeric
*
* @return a Number; will not necessarily be the same type as {@param zeroClass}
*
* @throws ParseException if the input cannot be converted to a number and {@code throwParseExceptions} is true
*/
@Nullable
public static Number objectToNumber(
final String name,
final Object inputValue,
@Nullable final ValueType outputType,
final boolean throwParseExceptions
)
{
if (outputType != null && !outputType.isNumeric()) {
throw new IAE("Output type[%s] must be numeric", outputType);
}
final Number asNumber;
if (inputValue == null) {
asNumber = null;
} else if (inputValue instanceof Number) {
asNumber = (Number) inputValue;
} else if (inputValue instanceof String) {
try {
String metricValueString = StringUtils.removeChar(((String) inputValue).trim(), ',');
// Longs.tryParse() doesn't support leading '+', so we need to trim it ourselves
metricValueString = trimLeadingPlusOfLongString(metricValueString);
Number v = null;
// Try parsing as Long first, since it's significantly faster than Double parsing, and also there are various
// integer numbers that can be represented as Long but cannot be represented as Double.View on GitHub (pinned to 9b90983fd2)
Solutions
- Change the outputType argument to a numeric ValueType: ValueType.LONG, ValueType.FLOAT, or ValueType.DOUBLE.
- Pass null for outputType to have Druid auto-detect the numeric type from the input value.
- If a string is genuinely needed, use Rows.objectToStrings instead of objectToNumber.
Example fix
// before
Number n = Rows.objectToNumber("metric", inputValue, ValueType.STRING, true);
// after
Number n = Rows.objectToNumber("metric", inputValue, ValueType.DOUBLE, true); Defensive patterns
Strategy: type-guard
Validate before calling
if (outputType != null && !outputType.isNumeric()) {
throw new IllegalArgumentException("outputType must be numeric: " + outputType);
} Type guard
boolean isNumericOutput(@Nullable ValueType t) {
return t == null || t == ValueType.LONG || t == ValueType.FLOAT || t == ValueType.DOUBLE;
} Try / catch
try {
return Rows.objectToNumber(name, value, outputType, true);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("must be numeric")) {
outputType = null; // fall back to auto-detect
return Rows.objectToNumber(name, value, null, true);
}
throw e;
} Prevention
- Only pass LONG, FLOAT, DOUBLE, or null as outputType to objectToNumber.
- Prefer the 3-arg overload (auto-detect) unless an explicit numeric type is required.
- Derive outputType from the aggregator's declared type and assert it is numeric at spec load time.
When it happens
Trigger: Calling Rows.objectToNumber(name, inputValue, ValueType.STRING, true) (or any non-numeric ValueType) directly; passing a column type expression or metric type spec that resolves to a non-numeric ValueType into a numeric aggregator/extraction path that delegates to objectToNumber.
Common situations: Aggregator specs where the type is mistakenly set to "string" while using floatSum/longSum style aggregation; custom code copying the 3-arg overload and adding an explicit outputType; type specs auto-derived from a dimension whose type was configured incorrectly.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unknown type[%s] for field[%s]
- Item must either be a String or StringTuple
- Cannot deserialize type[%s] to an RoaringBitmap64Counter:
- Cannot add / to a Spectator Histogram
- Expected a Number, but received [%s] of type [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/c17b951dc0f904e0.
Report an issue: GitHub.