{"record":{"id":"d62eb5eb78266141","repo":"apache/pulsar","slug":"other-messageid-not-have-topic","errorCode":null,"errorMessage":"Other MessageId not have topic ","messagePattern":"Other MessageId not have topic ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/MultiMessageIdImpl.java","lineNumber":76,"sourceCode":"                \"expected MultiMessageIdImpl object. Got instance of \" + o.getClass().getName());\n        }\n\n        MultiMessageIdImpl other = (MultiMessageIdImpl) o;\n        Map<String, MessageId> otherMap = other.getMap();\n\n        if ((map == null || map.isEmpty()) && (otherMap == null || otherMap.isEmpty())) {\n            return 0;\n        }\n\n        if (otherMap == null || map == null || otherMap.size() != map.size()) {\n            throw new IllegalArgumentException(\"Current size and other size not equals\");\n        }\n\n        int result = 0;\n        for (Entry<String, MessageId> entry : map.entrySet()) {\n            MessageId otherMessage = otherMap.get(entry.getKey());\n            if (otherMessage == null) {\n                throw new IllegalArgumentException(\n                    \"Other MessageId not have topic \" + entry.getKey());\n            }\n\n            int currentResult = entry.getValue().compareTo(otherMessage);\n            if (result == 0) {\n                result = currentResult;\n            } else if (currentResult == 0) {\n                continue;\n            } else if (result != currentResult) {\n                throw new IllegalArgumentException(\n                    \"Different MessageId in Map get different compare result\");\n            } else {\n                continue;\n            }\n        }\n\n        return result;\n    }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/MultiMessageIdImpl.java#L58-L94","documentation":"During MultiMessageIdImpl.compareTo, every topic key in the current map must exist in the other map; if otherMap.get(topic) returns null it throws IllegalArgumentException('Other MessageId not have topic ' + topic). Even with equal sizes, the key sets can differ (e.g. re-partitioning renamed topics, or cursors built from different topic lists).","triggerScenarios":"Comparing two multi-partition cursors whose topic/partition key sets are disjoint or partially overlapping with same size — e.g. one built from partitions of topic 'a-partition-' and the other after a partition count change that yields different keys, or cursors for different topics entirely.","commonSituations":"Re-partitioned topics; cursors from topics with different partition naming; code that builds MultiMessageIdImpl from ad-hoc maps with mismatched keys; comparing cursors across different partitioned topics by mistake.","solutions":["Verify both cursors cover the same topic set (compare key sets) before comparing","Normalize cursor construction: always build the multi-id from the current topic partition list via the client admin/lookup, never from stored partial maps","After a partition change, migrate the stored cursor per key: for keys present keep them, for missing keys default to earliest","Catch IllegalArgumentException and rebuild the cursor for the actual partition set"],"exampleFix":"// before\nint r = a.compareTo(b); // 'Other MessageId not have topic ...'\n// after\nif (!a.getMap().keySet().equals(b.getMap().keySet())) {\n    b = rebuildCursorForTopics(a.getMap().keySet()); // align key sets first\n}\nint r = a.compareTo(b);","handlingStrategy":"validation","validationCode":"boolean sameTopics(MultiMessageIdImpl a, MultiMessageIdImpl b) {\n    return a.getMap().keySet().equals(b.getMap().keySet());\n}","typeGuard":"boolean comparableKeySets(MultiMessageIdImpl a, MultiMessageIdImpl b) {\n    return a.getMap().keySet().equals(b.getMap().keySet());\n}","tryCatchPattern":"try {\n    int r = a.compareTo(b);\n} catch (IllegalArgumentException e) {\n    // key sets differ: rebuild the cursor over the actual partition set\n}","preventionTips":["Always construct multi-ids from the same authoritative partition list","Validate key-set equality before comparison","Migrate stored cursors key-by-key when partition naming changes"],"tags":["pulsar","messageid","partitioned","compareto","illegal-argument"],"backgroundTag":"messageid-topic-set-mismatch","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}