{"record":{"id":"dddf4e36b21d8526","repo":"apache/druid","slug":"stringfirstaggregator-does-not-support-getfloat-dddf4e","errorCode":null,"errorMessage":"StringFirstAggregator does not support getFloat()","messagePattern":"StringFirstAggregator does not support getFloat\\(\\)","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastBufferAggregator.java","lineNumber":115,"sourceCode":"            buf,\n            position,\n            new SerializablePairLongString(time, value),\n            maxStringBytes\n        );\n      }\n    }\n  }\n\n  @Override\n  public Object get(ByteBuffer buf, int position)\n  {\n    return StringFirstLastUtils.readPair(buf, position);\n  }\n\n  @Override\n  public float getFloat(ByteBuffer buf, int position)\n  {\n    throw new UnsupportedOperationException(\"StringFirstAggregator does not support getFloat()\");\n  }\n\n  @Override\n  public long getLong(ByteBuffer buf, int position)\n  {\n    throw new UnsupportedOperationException(\"StringFirstAggregator does not support getLong()\");\n  }\n\n  @Override\n  public double getDouble(ByteBuffer buf, int position)\n  {\n    throw new UnsupportedOperationException(\"StringFirstAggregator does not support getDouble()\");\n  }\n\n  @Override\n  public void close()\n  {\n    // no resources to cleanup","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastBufferAggregator.java#L97-L133","documentation":"StringLastBufferAggregator is the buffer-backed (off-heap) variant of the string-last aggregator. It stores timestamp/string pairs in ByteBuffers and cannot return a float, so getFloat(ByteBuffer,int) throws UnsupportedOperationException. The message text references StringFirstAggregator due to shared/copied message strings in this package.","triggerScenarios":"Calling getFloat(buf, position) on a StringLastBufferAggregator, typically when result extraction iterates buffer aggregators assuming numeric column types.","commonSituations":"Custom query layers or group-by result readers calling float accessors on string metrics; generic aggregation harnesses/tests treating all BufferAggregators as numeric.","solutions":["Use the string pair reader (StringFirstLastUtils.readPair) / get() path to obtain the value","Use a float-typed aggregator (floatLast/doubleFirst variants) if a float is required","Branch on the factory's type name before invoking typed accessors"],"exampleFix":"// before\nfloat f = bufAgg.getFloat(buf, position); // throws\n// after\nString[] pair = StringFirstLastUtils.readPair(buf, position); // [time, value]\nObject v = bufAgg.get(buf, position);","handlingStrategy":"type-guard","validationCode":"if (\"string\".equals(factory.getTypeName())) { /* use StringFirstLastUtils.readPair */ }","typeGuard":"static boolean hasFloatAccessor(AggregatorFactory f) { return f.getTypeName().equals(\"float\"); }","tryCatchPattern":"try { f = bufAgg.getFloat(buf, pos); } catch (UnsupportedOperationException e) { f = Float.NaN; }","preventionTips":["Only call getFloat on float-typed buffer aggregators","Use get(buf, position) generically and convert afterwards","Type-dispatch result extraction on the factory type name"],"tags":["java","druid","aggregation","buffer-aggregator","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-14T05:17:10.506Z"}