{"record":{"id":"c2e219d6da46cfb8","repo":"apache/druid","slug":"expected-instance-of-s-got-s-c2e219","errorCode":null,"errorMessage":"Expected instance of %s, got %s","messagePattern":"Expected instance of (.+?), got (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/SeekableStreamSequenceNumbers.java","lineNumber":59,"sourceCode":"   */\n  String getStream();\n\n  /**\n   * Returns whether the sequence number data is for possibly multiple streams / topics.\n   */\n  default boolean isMultiTopicPartition()\n  {\n    return false;\n  }\n\n  /**\n   * throws exception if this class and other class are not equal\n   * @param other the other instance to compare.\n   */\n  default void validateSequenceNumbersBaseType(SeekableStreamSequenceNumbers<PartitionIdType, SequenceOffsetType> other)\n  {\n    if (this.getClass() != other.getClass()) {\n      throw new IAE(\n          \"Expected instance of %s, got %s\",\n          this.getClass().getName(),\n          other.getClass().getName()\n      );\n    }\n  }\n\n  /**\n   * Returns a map of partitionId -> sequenceNumber.\n   */\n  Map<PartitionIdType, SequenceOffsetType> getPartitionSequenceNumberMap();\n\n  /**\n   * Merges this and the given other and returns the merged result.\n   *\n   * @see DataSourceMetadata#plus\n   */\n  SeekableStreamSequenceNumbers<PartitionIdType, SequenceOffsetType> plus(","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/SeekableStreamSequenceNumbers.java#L41-L77","documentation":"SeekableStreamSequenceNumbers.validateSequenceNumbersBaseType ensures that two sequence-numbers objects used in the same operation are of the exact same concrete class (e.g. KafkaSequenceNumbers vs KinesisSequenceNumbers, or start vs end numbers types). If 'other' is an instance of a different class, it throws IllegalArgumentException because offsets/partitions from incompatible stream types cannot be compared or merged.","triggerScenarios":"Comparing or composing SeekableStreamSequenceNumbers where this.getClass() != other.getClass() — e.g. mixing KafkaSequenceNumbers with KinesisSequenceNumbers, or a supervisor/task passing an end-sequence-numbers object of a different stream type into validateEqualPartitionOffsets.","commonSituations":"Copying a supervisor spec from Kafka to Kinesis without changing the sequenceNumbers class; programmatically constructing sequence numbers with the wrong generic types; submitting an ioConfig where start/end sequence numbers were built by different stream implementations.","solutions":["Use the correct SequenceNumbers factory for the stream type (KafkaSequenceNumbers.of / KinesisSequenceNumbers.of) for both start and end sequence numbers.","Ensure the supervisor spec's ioConfig.sequenceNumbers objects all come from the same streaming platform as the task type.","If writing custom code, check the concrete class (e.g. instanceof KafkaSequenceNumbers) before calling methods that validate equality against another sequence numbers object.","Fix any spec template/serialization that silently drops the platform-specific subtype during JSON round-trips."],"exampleFix":"// before: mixing types\nSeekableStreamSequenceNumbers<?, ?> start = KinesisSequenceNumbers.of(...);\nSeekableStreamSequenceNumbers<?, ?> end = KafkaSequenceNumbers.of(...);\nstart.validateEqualPartitionOffsets(end);\n// after: use matching types\nKafkaSequenceNumbers<?> start = KafkaSequenceNumbers.of(...);\nKafkaSequenceNumbers<?> end = KafkaSequenceNumbers.of(...);\nstart.validateEqualPartitionOffsets(end);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"if (start.getClass() != end.getClass()) { throw new IllegalArgumentException(\"sequence numbers from different stream types\"); } // or: require KafkaSequenceNumbers start/end both before calling validateEqualPartitionOffsets","tryCatchPattern":"try { start.validateEqualPartitionOffsets(end); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Expected instance of\")) { rebuildSequenceNumbersForStreamType(); } else { throw e; } }","preventionTips":["Always build start/end sequence numbers with the same factory (Kafka/Kinesis)","Never copy sequenceNumbers blocks between Kafka and Kinesis specs","Verify JSON round-trips preserve the platform-specific subtype"],"tags":["druid","kafka","kinesis","type-mismatch","sequence-numbers"],"backgroundTag":"type-mismatch","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}