apache/druid · error · java.lang.UnsupportedOperationException

StringFirstAggregator does not support getFloat()

Error message

StringFirstAggregator does not support getFloat()

What it means

StringFirstBufferAggregator buffers the earliest string value per group; the buffered result is a serialized string pair, not numeric. getFloat(ByteBuffer,int) is unsupported and always throws UnsupportedOperationException, indicating the caller used a numeric read on a string aggregate slot.

Source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/firstlast/first/StringFirstBufferAggregator.java:115

            buf,
            position,
            new SerializablePairLongString(time, value),
            maxStringBytes
        );
      }
    }
  }

  @Override
  public Object get(ByteBuffer buf, int position)
  {
    return StringFirstLastUtils.readPair(buf, position);
  }

  @Override
  public float getFloat(ByteBuffer buf, int position)
  {
    throw new UnsupportedOperationException("StringFirstAggregator does not support getFloat()");
  }

  @Override
  public long getLong(ByteBuffer buf, int position)
  {
    throw new UnsupportedOperationException("StringFirstAggregator does not support getLong()");
  }

  @Override
  public double getDouble(ByteBuffer buf, int position)
  {
    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 buffered value via get(buf, position), which deserializes the string pair.
  2. Remove numeric outputType/post-aggregations on stringFirst.
  3. Use FloatFirst aggregator for numeric earliest values.
  4. Type-check the aggregator before calling numeric buffer getters.

Example fix

// before
float v = bufAggregator.getFloat(buf, pos);
// after
Object v = bufAggregator.get(buf, pos); // SerializablePairLongString
Defensive patterns

Strategy: type-guard

Validate before calling

if (bufAggregator instanceof StringFirstBufferAggregator) {
  Object v = bufAggregator.get(buf, position);
} else {
  float v = bufAggregator.getFloat(buf, position);
}

Type guard

boolean supportsFloat(BufferAggregator a) {
  return !(a instanceof StringFirstBufferAggregator);
}

Try / catch

try {
  return agg.getFloat(buf, pos);
} catch (UnsupportedOperationException e) {
  Object pair = agg.get(buf, pos);
  return pair == null ? 0f : Float.parseFloat(String.valueOf(((SerializablePairLongString) pair).rhs));
}

Prevention

When it happens

Trigger: Calling getFloat(buf, position) on a StringFirstBufferAggregator buffer — typically generic aggregation-result code that reads the group's cell as a float, or a post-aggregator assuming float output.

Common situations: Custom aggregation pipelines reading buffer aggregator cells uniformly as numeric; query plans with numeric outputType over stringFirst; framework code paths that iterate numeric getters.

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