apache/druid · error · IllegalArgumentException

Expected instance of %s, got %s

Error message

Expected instance of %s, got %s

What it means

KafkaDataSourceMetadata.compareTo() only knows how to compare against another instance of the same concrete class; comparing against a different DataSourceMetadata subclass throws IAE('Expected instance of %s, got %s').

Source

Thrown at extensions-core/kafka-indexing-service/src/main/java/org/apache/druid/indexing/kafka/KafkaDataSourceMetadata.java:108

      return this;
    }
  }

  @Override
  protected SeekableStreamDataSourceMetadata<KafkaTopicPartition, Long> createConcreteDataSourceMetaData(
      SeekableStreamSequenceNumbers<KafkaTopicPartition, Long> seekableStreamSequenceNumbers
  )
  {
    return new KafkaDataSourceMetadata(seekableStreamSequenceNumbers, getBoundedStreamConfig());
  }

  @Override
  // This method is to compare KafkaDataSourceMetadata.
  // It compares this and other SeekableStreamSequenceNumbers using naturalOrder comparator.
  public int compareTo(KafkaDataSourceMetadata other)
  {
    if (!getClass().equals(other.getClass())) {
      throw new IAE(
          "Expected instance of %s, got %s",
          this.getClass().getName(),
          other.getClass().getName()
      );
    }
    return getSeekableStreamSequenceNumbers().compareTo(other.getSeekableStreamSequenceNumbers(), Comparator.naturalOrder());
  }

  @Override
  public boolean matches(DataSourceMetadata other)
  {
    if (!getClass().equals(other.getClass())) {
      return false;
    }
    KafkaDataSourceMetadata thisPlusOther = (KafkaDataSourceMetadata) plus(other);
    if (thisPlusOther.equals(other.plus(this))) {
      return true;
    }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure only one concrete KafkaDataSourceMetadata class is used for a datasource; migrate/merge stored metadata
  2. Do not compare metadata objects of different datasources/types
  3. If comparing arbitrary metadata, use equals or type-check first

Example fix

// before
metadataA.compareTo(metadataB); // may be a different subclass
// after
if (metadataA.getClass().equals(metadataB.getClass())) { metadataA.compareTo(metadataB); }
Defensive patterns

Strategy: type-guard

Validate before calling

if (a.getClass() != b.getClass()) throw new IllegalArgumentException("cannot compare different metadata types");

Type guard

boolean comparable(org.apache.druid.metadata.DateWeightedVector... ) {} // no; use: boolean isSameClass(DataSourceMetadata a, DataSourceMetadata b) { return a.getClass().equals(b.getClass()); }

Try / catch

try {
  return a.compareTo(b);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Expected instance of")) { return 0; /* or handle as incomparable */ }
  throw e;
}

Prevention

When it happens

Trigger: Calling compareTo (e.g. during metadata segment sorting/merging in coordinator/handoff paths) with a KafkaDataSourceMetadata of a different concrete class or another datasource metadata type.

Common situations: Mixing datasource metadata types (e.g. legacy vs current classes after a version upgrade) for the same datasource in metadata storage.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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