apache/pulsar · warning · IllegalArgumentException
Different MessageId in Map get different compare result
Error message
Different MessageId in Map get different compare result
What it means
MultiMessageIdImpl.compareTo demands a consistent total ordering: every per-topic comparison must yield the same sign (all greater, all equal, or all smaller). If per-partition comparisons disagree (some topics ahead, some behind), no valid ordering exists and it throws IllegalArgumentException('Different MessageId in Map get different compare result'). The class documents itself as only returning a value when all ids are uniformly bigger/smaller.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/MultiMessageIdImpl.java:86
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) {
throw new IllegalArgumentException(
"Other MessageId not have topic " + entry.getKey());
}
int currentResult = entry.getValue().compareTo(otherMessage);
if (result == 0) {
result = currentResult;
} else if (currentResult == 0) {
continue;
} else if (result != currentResult) {
throw new IllegalArgumentException(
"Different MessageId in Map get different compare result");
} else {
continue;
}
}
return result;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MultiMessageIdImpl) {
MultiMessageIdImpl other = (MultiMessageIdImpl) obj;
try {
return compareTo(other) == 0;
} catch (IllegalArgumentException e) {
return false;View on GitHub (pinned to 820761864e)
Solutions
- Don't compare multi-partition cursors with compareTo for ordering decisions; instead compare per-partition MessageIdImpl individually and define your own policy (e.g. min/max per topic)
- If you need 'has this cursor reached X', check per-partition containment (every partition's id >= target for that partition) rather than compareTo
- Store per-partition cursors and compare each independently on resume
- Catch IllegalArgumentException and fall back to per-partition comparison
Example fix
// before
boolean ahead = myCursor.compareTo(otherCursor) > 0; // often throws on skewed progress
// after
boolean ahead = true;
for (Map.Entry<String, MessageId> e : myCursor.getMap().entrySet()) {
MessageId otherId = otherCursor.getMap().get(e.getKey());
if (e.getValue().compareTo(otherId) < 0) { ahead = false; break; }
} Defensive patterns
Strategy: try-catch
Validate before calling
// per-partition skew check before compareTo
boolean uniformlyOrdered(MultiMessageIdImpl a, MultiMessageIdImpl b, int sign) {
return a.getMap().entrySet().stream()
.allMatch(e -> sign * e.getValue().compareTo(b.getMap().get(e.getKey())) >= 0);
} Type guard
boolean hasConsistentOrder(MultiMessageIdImpl a, MultiMessageIdImpl b) {
// true only if every per-topic comparison has the same sign
return uniformlyOrdered(a, b, 1) || uniformlyOrdered(a, b, -1);
} Try / catch
try {
int r = a.compareTo(b);
} catch (IllegalArgumentException e) {
// skewed progress: fall back to per-partition comparison with your own policy (min/max)
} Prevention
- Don't assume a total order across independent partitions; compare per-partition ids
- Implement 'reached target' checks as per-partition containment, not compareTo
- Catch IllegalArgumentException wherever partitioned cursors are compared
When it happens
Trigger: Comparing two multi-partition cursors where the partitions have advanced unevenly — e.g. one consumer is ahead on partition 0 but behind on partition 1. This is the normal state for independent partitions, so direct compareTo between arbitrary cursors frequently hits this.
Common situations: Checkpoint/resume logic assuming a total order over partitioned cursors; comparing live cursors of two consumers on a partitioned topic with skewed consumption; sorting a list of multi-partition message ids.
Related errors
- expected MultiMessageIdImpl object. Got instance of
- Current size and other size not equals
- Other MessageId not have topic
- isDuplicated cannot accept
- ResourceGroupCreate: Invalid null ResourceGroup config
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/6e5967af0da42c70.
Report an issue: GitHub.