{"record":{"id":"ad67110551c32c8a","repo":"apache/druid","slug":"stringlastaggregator-does-not-support-getlong","errorCode":null,"errorMessage":"StringLastAggregator does not support getLong()","messagePattern":"StringLastAggregator does not support getLong\\(\\)","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregator.java","lineNumber":101,"sourceCode":"    }\n  }\n\n  @Override\n  public Object get()\n  {\n    return new SerializablePairLongString(lastTime, StringUtils.chop(lastValue, maxStringBytes));\n  }\n\n  @Override\n  public float getFloat()\n  {\n    throw new UnsupportedOperationException(\"StringLastAggregator does not support getFloat()\");\n  }\n\n  @Override\n  public long getLong()\n  {\n    throw new UnsupportedOperationException(\"StringLastAggregator does not support getLong()\");\n  }\n\n  @Override\n  public double getDouble()\n  {\n    throw new UnsupportedOperationException(\"StringLastAggregator does not support getDouble()\");\n  }\n\n  @Override\n  public void close()\n  {\n    // no resources to cleanup\n  }\n}\n","sourceCodeStart":83,"sourceCodeEnd":116,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregator.java#L83-L116","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use the string accessor (aggregate() then inspect the value via the appropriate result path / getSerializedString / result object) instead of getLong()","Change the aggregation to a numeric aggregator (e.g. doubleLast/longFirst) if a numeric result is actually needed","Check the aggregator's type (AggregatorFactory.getTypeName()) before dispatching to numeric accessors","If getLong is legitimately needed, convert the string value at query time with SQL CAST"],"exampleFix":"// before\nAggregator agg = factory.factorize(colSelectorFactory);\nlong v = agg.getLong(); // throws UnsupportedOperationException\n// after\nif (\"string\".equals(factory.getTypeName())) {\n  Object v = agg.get(); // string result\n} else {\n  long v2 = agg.getLong();\n}","handlingStrategy":"type-guard","validationCode":"if (\"string\".equals(factory.getTypeName())) { /* use string result path */ }","typeGuard":"static boolean supportsLong(AggregatorFactory f) { return !\"string\".equals(f.getTypeName()) && !\"hyperUnique\".equals(f.getTypeName()); }","tryCatchPattern":"try { v = agg.getLong(); } catch (UnsupportedOperationException e) { v = parseOrNull(String.valueOf(agg.get())); }","preventionTips":["Consult AggregatorFactory.getTypeName() before calling typed accessors","Prefer SQL CAST or a numeric aggregator over numeric accessors on string aggregators","Keep custom result code type-dispatched, not accessor-uniform"],"tags":["java","druid","aggregation","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}