apache/druid · error · java.lang.UnsupportedOperationException
StringFirstAggregator does not support getLong()
Error message
StringFirstAggregator does not support getLong()
What it means
StringFirstAggregator produces a string result (earliest value with its timestamp), so getLong() is unsupported and always throws UnsupportedOperationException. Numeric extraction from a string-first aggregate is invalid by design.
Source
Thrown at processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstAggregator.java:101
}
}
@Override
public Object get()
{
return new SerializablePairLongString(firstTime, StringUtils.chop(firstValue, maxStringBytes));
}
@Override
public float getFloat()
{
throw new UnsupportedOperationException("StringFirstAggregator does not support getFloat()");
}
@Override
public long getLong()
{
throw new UnsupportedOperationException("StringFirstAggregator does not support getLong()");
}
@Override
public double getDouble()
{
throw new UnsupportedOperationException("StringFirstAggregator does not support getDouble()");
}
@Override
public void close()
{
// no resources to cleanup
}
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Read the value as a string/object via the aggregator's get() method instead of getLong().
- Remove or correct the outputType/post-aggregator that declares a long result for stringFirst.
- Use LongFirstAggregator (type "longFirst") if the earliest numeric value is desired.
- Cast/parse explicitly at the SQL layer only after retrieving the string, if a numeric interpretation is truly needed.
Example fix
// before
{"type":"stringFirst","name":"s","fieldName":"col","outputType":"LONG"}
// after
{"type":"stringFirst","name":"s","fieldName":"col"} Defensive patterns
Strategy: type-guard
Validate before calling
if (aggregator instanceof StringFirstAggregator) {
Object v = aggregator.get();
} else {
long v = aggregator.getLong();
} Type guard
boolean supportsLong(Aggregator a) {
return !(a instanceof StringFirstAggregator);
} Try / catch
try {
return agg.getLong();
} catch (UnsupportedOperationException e) {
Object pair = agg.get();
return pair == null ? 0L : Long.parseLong(String.valueOf(((SerializablePairLongString) pair).rhs));
} Prevention
- Set outputType correctly (string) for stringFirst.
- Use longFirst for numeric earliest values.
- Avoid generic numeric getter loops over heterogeneous aggregators.
When it happens
Trigger: Calling getLong() on StringFirstAggregator — e.g. a post-aggregation or finalizer that assumes a long output, or a numeric outputType configured for stringFirst.
Common situations: Misconfigured native query with outputType Long on a stringFirst aggregator; custom code reading aggregator values via getLong; SQL planner mismatch producing a long-typed expression over stringFirst.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- StringFirstAggregator does not support getFloat()
- StringFirstAggregator does not support getDouble()
- StringFirstAggregator does not support getFloat()
- StringFirstAggregator does not support getLong()
- StringFirstAggregator does not support getDouble()
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/5ac0b633cad26327.
Report an issue: GitHub.