apache/druid · error · IllegalStateException

Incompatible serializer for type

Error message

Incompatible serializer for type[%s] already exists. Expected [%s], found [%s].

What it means

ComplexMetrics.registerSerde registers an ObjectStrategy-based serializer for a named complex type (e.g. "hyperUnique", "quantilesDoublesSketch") in a static registry. If a serde for the same type name is already registered from a DIFFERENT class, registration fails with this ISE, because silently swapping serializers would corrupt reading of existing segments. Registering the same class twice is idempotent and allowed.

Solutions

  1. Identify the two extensions/jars registering the same complex type name and remove the duplicate or conflicting dependency from the classpath.
  2. Ensure you register exactly one serde class per type name at startup; guard registration so it happens once.
  3. If you intentionally changed the serde implementation, use a new complex type name instead of reusing the old one, or revert to the original class.
  4. Check druid.extensions.loadList and extension directories for jars that register the same type.

Example fix

// before
ComplexMetrics.registerSerde("mySketch", new MySketchSerdeV2()); // conflicts with V1 already registered
// after
// keep the same class as the one already registered, or use a distinct type name:
ComplexMetrics.registerSerde("mySketchV2", new MySketchSerdeV2());
Defensive patterns

Strategy: validation

Validate before calling

ObjectStrategy<?> existing = ComplexMetrics.getSerdeForType("mySketch");
if (existing != null && !existing.getClass().equals(MySketchSerdeV2.class)) {
    throw new IllegalStateException("Type mySketch already bound to " + existing.getClass().getName());
}
ComplexMetrics.registerSerde("mySketch", new MySketchSerdeV2());

Prevention

When it happens

Trigger: Calling ComplexMetrics.registerSerde(typeName, serde) when the static COMPLEX_SERIALIZERS map already holds an entry for typeName whose serde class differs from the new serde's class.

Common situations: Loading two extensions that both register a serde for the same complex type name (e.g. two custom sketch extensions registering the same typeName); a classpath containing duplicate/conflicting extension jars; renaming or refactoring a serde class while an old segment's Druid version re-registers the old class under the same name; calling registerSerde again with a new serializer implementation for the same type.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/b859a38ae1e823a6. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/serde/ComplexMetrics.java:60

   * Register a serde name -> ComplexMetricSerde mapping.
   *
   * <p>
   * If the specified serde key string is already used and the supplied ComplexMetricSerde is not of the same
   * type as the existing value in the map for said key, an ISE is thrown.
   * </p>
   *
   * @param type The serde name used as the key in the map.
   * @param serde The ComplexMetricSerde object to be associated with the 'type' in the map.
   */
  public static void registerSerde(String type, ComplexMetricSerde serde)
  {
    COMPLEX_SERIALIZERS.compute(type, (key, value) -> {
      if (value == null) {
        TypeStrategies.registerComplex(type, serde.getTypeStrategy());
        return serde;
      } else {
        if (!value.getClass().getName().equals(serde.getClass().getName())) {
          throw new ISE(
              "Incompatible serializer for type[%s] already exists. Expected [%s], found [%s].",
              key,
              serde.getClass().getName(),
              value.getClass().getName()
          );
        } else {
          return value;
        }
      }
    });
  }

  /**
   * Unregister a serde name -> ComplexMetricSerde mapping.
   *
   * If the specified serde key string is not in use, does nothing.
   *
   * Only expected to be used in tests.

View on GitHub (pinned to 9b90983fd2)