apache/druid · error · UnsupportedOperationException
Not implemented
Error message
Not implemented
What it means
Bitmap64ExactCountMergeBufferAggregator.getLong(ByteBuffer, int) is an intentionally unimplemented stub. The merge buffer aggregator maintains an underlying counter object per slot (counterCache) whose cardinality is exposed through its own accessor; getLong() on the buffer aggregator itself is not supported and always throws UnsupportedOperationException("Not implemented").
Source
Thrown at extensions-contrib/druid-exact-count-bitmap/src/main/java/org/apache/druid/query/aggregation/exact/count/bitmap64/Bitmap64ExactCountMergeBufferAggregator.java:67
{
Object x = selector.getObject();
if (x == null) {
return;
}
Bitmap64 bitmap64Counter = counterCache.get(buf).get(position);
bitmap64Counter.fold((RoaringBitmap64Counter) x);
}
@Override
public Object get(ByteBuffer buf, int position)
{
return counterCache.get(buf).get(position);
}
@Override
public long getLong(ByteBuffer buf, int position)
{
throw new UnsupportedOperationException("Not implemented");
}
@Override
public double getDouble(ByteBuffer buf, int position)
{
throw new UnsupportedOperationException("Not implemented");
}
@Override
public float getFloat(ByteBuffer buf, int position)
{
throw new UnsupportedOperationException("Not implemented");
}
@Override
public void close()
{
counterCache.clear();View on GitHub (pinned to 9b90983fd2)
Solutions
- Read the counter via get(buf, position) (counterCache.get(buf).get(position)) and take its cardinality accessor.
- Consume results through the standard finalization path, which uses the counter object's own accessor rather than BufferAggregator.getLong.
- Adjust post-aggregator/input-type declarations so the merge aggregation isn't read via getLong.
- Implement getLong() in the extension delegating to the counter value if direct access is required.
Example fix
// before long v = bufferAggregator.getLong(buf, position); // after Object counter = bufferAggregator.get(buf, position); long v = (counter instanceof Number) ? ((Number) counter).longValue() : 0L;
Defensive patterns
Strategy: type-guard
Validate before calling
Object c = bufferAggregator.get(buf, position); boolean ok = c instanceof Number || c instanceof Roaring64Bitmap; // read accordingly
Type guard
boolean isCounterSlot(BufferAggregator agg, ByteBuffer buf, int pos) { return agg.get(buf, pos) instanceof Number; } Try / catch
try { v = bufferAggregator.getLong(buf, position); } catch (UnsupportedOperationException e) { v = ((Number) bufferAggregator.get(buf, position)).longValue(); } Prevention
- Read merge slots via get(buf, position) (counterCache-backed) instead of getLong
- Keep the aggregation output type LONG in query specs
- Use standard engine finalization rather than direct BufferAggregator getters
When it happens
Trigger: Finalization calls bufferAggregator.getLong(buf, position) on the bitmap64 merge aggregation slot — e.g. generic group-by/timeseries result readers or post-aggregators typed LONG reading the slot directly.
Common situations: Custom query engines reading aggregation slots with getLong by default; tests enumerating BufferAggregator accessors; code ported from other aggregators (long sum) that assumes getLong works for all buffer aggregators.
Related errors
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/260c42e3fd9792a0.
Report an issue: GitHub.