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

  1. Extend fromBuffer (or upgrade Druid) to support the specific pairClass used when writing the data
  2. Regenerate/rewrite the intermediate data using a supported pair type (SerializablePairLongString)
  3. Verify all cluster nodes/extensions run the same version so writers and readers agree on supported types
  4. 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

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


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)