apache/druid · error · java.lang.UnsupportedOperationException

StringLastAggregator does not support getLong()

Error message

StringLastAggregator does not support getLong()

What it means

StringLastAggregator aggregates last string values per time column, so its numeric accessors are meaningless. The Aggregator interface requires getFloat/getLong/getDouble, but a string-typed aggregator cannot produce numeric primitives, so all unsupported accessors throw UnsupportedOperationException. This is a deliberate contract guard, not a transient failure.

Solutions

  1. Use the string accessor (aggregate() then inspect the value via the appropriate result path / getSerializedString / result object) instead of getLong()
  2. Change the aggregation to a numeric aggregator (e.g. doubleLast/longFirst) if a numeric result is actually needed
  3. Check the aggregator's type (AggregatorFactory.getTypeName()) before dispatching to numeric accessors
  4. If getLong is legitimately needed, convert the string value at query time with SQL CAST

Example fix

// before
Aggregator agg = factory.factorize(colSelectorFactory);
long v = agg.getLong(); // throws UnsupportedOperationException
// after
if ("string".equals(factory.getTypeName())) {
  Object v = agg.get(); // string result
} else {
  long v2 = agg.getLong();
}
Defensive patterns

Strategy: type-guard

Validate before calling

if ("string".equals(factory.getTypeName())) { /* use string result path */ }

Type guard

static boolean supportsLong(AggregatorFactory f) { return !"string".equals(f.getTypeName()) && !"hyperUnique".equals(f.getTypeName()); }

Try / catch

try { v = agg.getLong(); } catch (UnsupportedOperationException e) { v = parseOrNull(String.valueOf(agg.get())); }

Prevention

When it happens

Trigger: Calling aggregator.getLong() on a StringLastAggregator instance, typically reached when a query/factory declares this aggregator but the row-reading or result-layer code assumes a numeric column type and invokes the long accessor.

Common situations: Running a last(string) aggregation and then post-processing results with numeric accessors; custom query tooling iterating Aggregator objects generically without consulting the aggregator's type; tests or plugins that expect all aggregators to be numeric.

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/ad67110551c32c8a. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregator.java:101

    }
  }

  @Override
  public Object get()
  {
    return new SerializablePairLongString(lastTime, StringUtils.chop(lastValue, maxStringBytes));
  }

  @Override
  public float getFloat()
  {
    throw new UnsupportedOperationException("StringLastAggregator does not support getFloat()");
  }

  @Override
  public long getLong()
  {
    throw new UnsupportedOperationException("StringLastAggregator does not support getLong()");
  }

  @Override
  public double getDouble()
  {
    throw new UnsupportedOperationException("StringLastAggregator does not support getDouble()");
  }

  @Override
  public void close()
  {
    // no resources to cleanup
  }
}

View on GitHub (pinned to 9b90983fd2)