apache/rocketmq · error · RuntimeException

Can't accept data with unmatched scope

Error message

Can't accept data with unmatched scope %s != %s

What it means

Non-force update of topic-queue mapping requires the new detail's scope to equal the stored one; a different scope (the namespace/domain a mapping belongs to) is rejected with RuntimeException. Scope is part of the mapping identity and must stay stable across updates.

Solutions

  1. Read the existing mapping's scope and submit the update with the identical scope value.
  2. Standardize which scope (global vs cluster/domain) manages this topic; don't interleave commands with different scope settings.
  3. If a genuine scope migration is needed, do it as a controlled migration (force path / recreate mapping), not an in-place update.
Defensive patterns

Strategy: validation

Validate before calling

TopicQueueMappingDetail old = manager.queryTopicQueueMapping(topic);
if (old != null && !newDetail.getScope().equals(old.getScope())) {
    newDetail.setScope(old.getScope()); // scope is immutable across updates
}

Type guard

boolean scopeMatches(TopicQueueMappingDetail oldD, TopicQueueMappingDetail newD) {
    return oldD == null || oldD.getScope().equals(newD.getScope());
}

Try / catch

catch (RuntimeException e) { if (e.getMessage().contains("unmatched scope")) { adoptStoredScope(); resubmit(); } else throw e; }

Prevention

When it happens

Trigger: updateTopicQueueMapping submitting detail with scope 'clusterA' while stored detail has scope 'domainA' (or full vs partial scope names) with equal-or-greater epoch.

Common situations: Mixing global-scope and cluster-scope mapping commands; tools upgraded between versions that change default scope strings; copying mapping config across environments with different scope configuration.

Related errors


AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14). Data as JSON: /api/errors/a4ba14db44f650b8. Report an issue: GitHub.

Appendix: source

Thrown at broker/src/main/java/org/apache/rocketmq/broker/topic/TopicQueueMappingManager.java:109

                topicQueueMappingTable.put(newDetail.getTopic(), newDetail);
                updated = true;
                return;
            }
            if (force) {
                //bakeup the old items
                oldDetail.getHostedQueues().forEach((queueId, items) -> {
                    newDetail.getHostedQueues().putIfAbsent(queueId, items);
                });
                topicQueueMappingTable.put(newDetail.getTopic(), newDetail);
                updated = true;
                return;
            }
            //do more check
            if (newDetail.getEpoch() < oldDetail.getEpoch()) {
                throw new RuntimeException(String.format("Can't accept data with small epoch %d < %d", newDetail.getEpoch(), oldDetail.getEpoch()));
            }
            if (!newDetail.getScope().equals(oldDetail.getScope())) {
                throw new RuntimeException(String.format("Can't accept data with unmatched scope %s != %s", newDetail.getScope(), oldDetail.getScope()));
            }
            boolean epochEqual = newDetail.getEpoch() == oldDetail.getEpoch();
            for (Integer globalId : oldDetail.getHostedQueues().keySet()) {
                List<LogicQueueMappingItem> oldItems = oldDetail.getHostedQueues().get(globalId);
                List<LogicQueueMappingItem> newItems = newDetail.getHostedQueues().get(globalId);
                if (newItems == null) {
                    if (epochEqual) {
                        throw new RuntimeException("Cannot accept equal epoch with null data");
                    } else {
                        newDetail.getHostedQueues().put(globalId, oldItems);
                    }
                } else {
                    TopicQueueMappingUtils.makeSureLogicQueueMappingItemImmutable(oldItems, newItems, epochEqual, isClean);
                }
            }
            topicQueueMappingTable.put(newDetail.getTopic(), newDetail);
            updated = true;
        }  finally {

View on GitHub (pinned to 293f588571)