apache/druid · error · ResourceLimitException
Unsupported pairClass type
Error message
Unsupported pairClass type: %s
What it means
The column-header deserializer (fromBuffer) can only reconstruct headers for pair types it knows, currently SerializablePairLongString. If the stored generic-pair serde was built with any other pair value type, the runtime pairClass cannot be mapped to a concrete header class and Druid throws RE. This usually means reading staged/intermediate store data written with an unsupported type.
Solutions
- Extend fromBuffer (or upgrade Druid) to support the specific pairClass used when writing the data
- Regenerate/rewrite the intermediate data using a supported pair type (SerializablePairLongString)
- Verify all cluster nodes/extensions run the same version so writers and readers agree on supported types
- Add the new pair class mapping to fromBuffer before deploying a custom serde
Example fix
// before
throw new RE(String.format(Locale.ENGLISH, "Unsupported pairClass type: %s", pairClass.getSimpleName()));
// after
if (pairClass.isAssignableFrom(SerializablePairLongDouble.class)) {
return new SerializablePairLongDoubleColumnHeader(bytes, minTimestamp);
}
throw new RE(String.format(Locale.ENGLISH, "Unsupported pairClass type: %s", pairClass.getSimpleName())); Defensive patterns
Strategy: try-catch
Validate before calling
if (!SerializablePairLongString.class.isAssignableFrom(pairClass)) {
throw new UnsupportedOperationException("pairClass " + pairClass + " header not supported by this reader");
} Type guard
boolean isSupportedPairClass(Class<?> pairClass) {
return SerializablePairLongString.class.isAssignableFrom(pairClass);
} Try / catch
try {
AbstractSerializablePairLongObjectColumnHeader h =
AbstractSerializablePairLongObjectColumnHeader.fromBuffer(bytes, minTimestamp, pairClass);
} catch (RuntimeException e) {
// fall back to unsupported-type handling / rewrite the intermediate store
} Prevention
- Keep writer and reader Druid versions/extensions aligned in the cluster
- Use supported pair types (SerializablePairLongString) in staged serdes
- Add header mappings for new pair classes before writing data with them
When it happens
Trigger: Reading a staged intermediate store whose header was written by an AbstractSerializablePairLongObjectStagedSerde parameterized with a pair class other than SerializablePairLongString, then calling fromBuffer to decode the header.
Common situations: Adding a new SerializablePairLongObject<T> serde in one Druid version and reading its output with a version lacking that header class; custom aggregators using non-String object types; cluster nodes with mismatched extension jars.
Related errors
- Error while reading distribution for interval
- FLOAT types are not supported natively by Druid expressions
- Incompatible serializer for type
- Object cannot be deserialized to a Moments Sketch:
- Unsupported expression type
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/6cfe4cb0edc01b54.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/query/aggregation/AbstractSerializablePairLongObjectColumnHeader.java:84
long minTimestamp = byteBuffer.getLong();
if (pairClass.isAssignableFrom(SerializablePairLongLong.class)) {
return new SerializablePairLongLongColumnHeader(bytes, minTimestamp);
}
if (pairClass.isAssignableFrom(SerializablePairLongDouble.class)) {
return new SerializablePairLongDoubleColumnHeader(bytes, minTimestamp);
}
if (pairClass.isAssignableFrom(SerializablePairLongFloat.class)) {
return new SerializablePairLongFloatColumnHeader(bytes, minTimestamp);
}
if (pairClass.isAssignableFrom(SerializablePairLongString.class)) {
return new SerializablePairLongStringColumnHeader(bytes, minTimestamp);
}
throw new RE(String.format(Locale.ENGLISH, "Unsupported pairClass type: %s", pairClass.getSimpleName()));
}
public abstract AbstractSerializablePairLongObjectDeltaEncodedStagedSerde<?> createSerde();
public void transferTo(WritableByteChannel channel) throws IOException
{
LongSerializer longSerializer = new LongSerializer();
channel.write(ByteBuffer.wrap(bytes));
channel.write(longSerializer.serialize(minValue));
}
public int getVersion()
{
return 0XFF & bytes[VERSION_INDEX];
}
public boolean isUseIntegerDeltas()View on GitHub (pinned to 9b90983fd2)