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

  1. Read the value as a string/object via the aggregator's get() method instead of getLong().
  2. Remove or correct the outputType/post-aggregator that declares a long result for stringFirst.
  3. Use LongFirstAggregator (type "longFirst") if the earliest numeric value is desired.
  4. 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

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


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/5ac0b633cad26327. Report an issue: GitHub.