apache/pulsar · warning · IllegalArgumentException
expected MultiMessageIdImpl object. Got instance of
Error message
expected MultiMessageIdImpl object. Got instance of
What it means
MultiMessageIdImpl.compareTo only knows how to compare against another MultiMessageIdImpl. Passing any other MessageId implementation (MessageIdImpl, BatchMessageIdImpl, TopicMessageIdImpl, etc.) throws IllegalArgumentException naming the offending class. Comparison across the single-partition and multi-partition id types is undefined in this class.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/MultiMessageIdImpl.java:57
}
// TODO: Add support for Serialization and Deserialization
// https://github.com/apache/pulsar/issues/4940
@Override
public byte[] toByteArray() {
throw new UnsupportedOperationException();
}
@Override
public int hashCode() {
return Objects.hash(map);
}
// If all messageId in map are same size, and all bigger/smaller than the other, return valid value.
@Override
public int compareTo(MessageId o) {
if (!(o instanceof MultiMessageIdImpl)) {
throw new IllegalArgumentException(
"expected MultiMessageIdImpl object. Got instance of " + o.getClass().getName());
}
MultiMessageIdImpl other = (MultiMessageIdImpl) o;
Map<String, MessageId> otherMap = other.getMap();
if ((map == null || map.isEmpty()) && (otherMap == null || otherMap.isEmpty())) {
return 0;
}
if (otherMap == null || map == null || otherMap.size() != map.size()) {
throw new IllegalArgumentException("Current size and other size not equals");
}
int result = 0;
for (Entry<String, MessageId> entry : map.entrySet()) {
MessageId otherMessage = otherMap.get(entry.getKey());
if (otherMessage == null) {View on GitHub (pinned to 820761864e)
Solutions
- Only compare MultiMessageIdImpl with MultiMessageIdImpl; unwrap TopicMessageIdImpl via getInnerMessageId() to compare at the partition level
- If you need cross-type comparison, convert the single id into a map keyed by topic and build a MultiMessageIdImpl, or compare ledgerId/entryId explicitly
- Guard with instanceof before calling compareTo
- Catch IllegalArgumentException around compareTo when ids come from mixed sources
Example fix
// before
int r = multiId.compareTo(singleId); // IllegalArgumentException
// after
if (multiId instanceof MultiMessageIdImpl && singleId instanceof MultiMessageIdImpl) {
int r = multiId.compareTo(singleId);
} else {
// compare per-topic inner ids instead
MessageId inner = ((TopicMessageIdImpl) singleId).getInnerMessageId();
...
} Defensive patterns
Strategy: type-guard
Validate before calling
Integer compareSafely(MessageId a, MessageId b) {
if (a instanceof MultiMessageIdImpl && b instanceof MultiMessageIdImpl) return a.compareTo(b);
return null; // cross-type comparison unsupported
} Type guard
boolean comparableMultiIds(MessageId a, MessageId b) {
return a instanceof MultiMessageIdImpl && b instanceof MultiMessageIdImpl;
} Try / catch
try {
int r = a.compareTo(b);
} catch (IllegalArgumentException e) {
// unwrap TopicMessageIdImpl / compare per-topic inner ids instead
} Prevention
- Only compare ids of the same concrete MessageId type
- Unwrap TopicMessageIdImpl.getInnerMessageId() before low-level comparisons
- Avoid generic MessageId comparators/sorters that mix partitioned and non-partitioned ids
When it happens
Trigger: Calling compareTo (directly or via equals/sorting) between a MultiMessageIdImpl and any non-MultiMessageIdImpl MessageId — e.g. comparing a partitioned-topic cursor to a message id from a single-partition consumer.
Common situations: Generic MessageId comparison/sorting code that mixes ids from partitioned and non-partitioned consumers; test utilities (testMultiMessageIdCompareto) passing the wrong type; mapping TopicMessageIdImpl results back without unwrapping.
Related errors
- Current size and other size not equals
- Other MessageId not have topic
- Different MessageId in Map get different compare result
- isDuplicated cannot accept
- ResourceGroupCreate: Invalid null ResourceGroup config
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/3188b20ddacd0580.
Report an issue: GitHub.