apache/pulsar · error · java.lang.IllegalArgumentException
Cannot compare with ${other.getClass()}
Error message
Cannot compare with ${other.getClass()} What it means
MessageIdV5.compareTo only supports comparing against other MessageIdV5 instances. If passed any other implementation of org.apache.pulsar.client.api.v5.MessageId, it throws IllegalArgumentException('Cannot compare with <class>') because segment-ordering semantics are undefined across implementations.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/MessageIdV5.java:338
int count = buf.getInt();
Map<Long, MessageId> out = new HashMap<>(count);
for (int i = 0; i < count; i++) {
long segId = buf.getLong();
int idLen = buf.getInt();
if (idLen < 0 || idLen > buf.remaining()) {
throw new IOException("Invalid MessageIdV5 data: bad inner id length");
}
byte[] idBytes = new byte[idLen];
buf.get(idBytes);
out.put(segId, MessageId.fromByteArray(idBytes));
}
return out;
}
@Override
public int compareTo(org.apache.pulsar.client.api.v5.MessageId other) {
if (!(other instanceof MessageIdV5 o)) {
throw new IllegalArgumentException("Cannot compare with " + other.getClass());
}
int cmp = Long.compare(this.segmentId, o.segmentId);
if (cmp != 0) {
return cmp;
}
return this.v4MessageId.compareTo(o.v4MessageId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof MessageIdV5 o)) {
return false;
}
return segmentId == o.segmentId && v4MessageId.equals(o.v4MessageId);
}View on GitHub (pinned to 820761864e)
Solutions
- Ensure all ids being compared are MessageIdV5 instances produced by this client.
- Convert or unwrap other implementations to MessageIdV5 before comparing.
- In tests, build expected values via MessageIdV5 (or its factory methods) rather than mocks.
- If you need mixed comparison, write a comparator that handles each type explicitly instead of relying on compareTo.
Example fix
// before
ids.sort(Comparator.naturalOrder()); // list mixes id types
// after
ids.sort((a, b) -> {
if (a instanceof MessageIdV5 a5 && b instanceof MessageIdV5 b5) return a5.compareTo(b5);
throw new IllegalStateException("Mixed id types in collection");
}); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(other instanceof MessageIdV5)) {
throw new IllegalArgumentException("compareTo requires MessageIdV5, got "
+ other.getClass().getName());
} Type guard
static boolean isComparableV5(org.apache.pulsar.client.api.v5.MessageId id) {
return id instanceof MessageIdV5;
} Try / catch
try {
cmp = a.compareTo(b);
} catch (IllegalArgumentException e) {
log.error("Mixed message id types in ordered collection: {}", e.getMessage());
} Prevention
- Keep collections of ordered ids homogeneous — only MessageIdV5 instances.
- Convert foreign id implementations to MessageIdV5 at ingestion boundaries.
- Use real MessageIdV5 instances (not mocks) in tests that exercise ordering.
When it happens
Trigger: Mixing message id types in the same collection (e.g. sorting a List mixing MessageIdV5 and another v5 MessageId implementation, or a sentinel/stub id), then calling Collections.sort or compareTo.
Common situations: Collecting ids from two client APIs into one set; a test helper returning a mock v5 MessageId; a custom MessageId implementation from a fork being compared with stock MessageIdV5.
Related errors
- Not supported operation on partitioned-topic
- Positions must not be null
- Invalid range ${range}
- Split service unit should be split into 2 service units.
- ResourceGroupCreate: Invalid null ResourceGroup config
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/05ae6a040c42a216.
Report an issue: GitHub.