{"record":{"id":"a4ba14db44f650b8","repo":"apache/rocketmq","slug":"can-t-accept-data-with-unmatched-scope-s-s","errorCode":null,"errorMessage":"Can't accept data with unmatched scope %s != %s","messagePattern":"Can't accept data with unmatched scope (.+?) != (.+?)","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"broker/src/main/java/org/apache/rocketmq/broker/topic/TopicQueueMappingManager.java","lineNumber":109,"sourceCode":"                topicQueueMappingTable.put(newDetail.getTopic(), newDetail);\n                updated = true;\n                return;\n            }\n            if (force) {\n                //bakeup the old items\n                oldDetail.getHostedQueues().forEach((queueId, items) -> {\n                    newDetail.getHostedQueues().putIfAbsent(queueId, items);\n                });\n                topicQueueMappingTable.put(newDetail.getTopic(), newDetail);\n                updated = true;\n                return;\n            }\n            //do more check\n            if (newDetail.getEpoch() < oldDetail.getEpoch()) {\n                throw new RuntimeException(String.format(\"Can't accept data with small epoch %d < %d\", newDetail.getEpoch(), oldDetail.getEpoch()));\n            }\n            if (!newDetail.getScope().equals(oldDetail.getScope())) {\n                throw new RuntimeException(String.format(\"Can't accept data with unmatched scope %s != %s\", newDetail.getScope(), oldDetail.getScope()));\n            }\n            boolean epochEqual = newDetail.getEpoch() == oldDetail.getEpoch();\n            for (Integer globalId : oldDetail.getHostedQueues().keySet()) {\n                List<LogicQueueMappingItem> oldItems = oldDetail.getHostedQueues().get(globalId);\n                List<LogicQueueMappingItem> newItems = newDetail.getHostedQueues().get(globalId);\n                if (newItems == null) {\n                    if (epochEqual) {\n                        throw new RuntimeException(\"Cannot accept equal epoch with null data\");\n                    } else {\n                        newDetail.getHostedQueues().put(globalId, oldItems);\n                    }\n                } else {\n                    TopicQueueMappingUtils.makeSureLogicQueueMappingItemImmutable(oldItems, newItems, epochEqual, isClean);\n                }\n            }\n            topicQueueMappingTable.put(newDetail.getTopic(), newDetail);\n            updated = true;\n        }  finally {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicQueueMappingManager.java#L91-L127","documentation":"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.","triggerScenarios":"updateTopicQueueMapping submitting detail with scope 'clusterA' while stored detail has scope 'domainA' (or full vs partial scope names) with equal-or-greater epoch.","commonSituations":"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.","solutions":["Read the existing mapping's scope and submit the update with the identical scope value.","Standardize which scope (global vs cluster/domain) manages this topic; don't interleave commands with different scope settings.","If a genuine scope migration is needed, do it as a controlled migration (force path / recreate mapping), not an in-place update."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"TopicQueueMappingDetail old = manager.queryTopicQueueMapping(topic);\nif (old != null && !newDetail.getScope().equals(old.getScope())) {\n    newDetail.setScope(old.getScope()); // scope is immutable across updates\n}","typeGuard":"boolean scopeMatches(TopicQueueMappingDetail oldD, TopicQueueMappingDetail newD) {\n    return oldD == null || oldD.getScope().equals(newD.getScope());\n}","tryCatchPattern":"catch (RuntimeException e) { if (e.getMessage().contains(\"unmatched scope\")) { adoptStoredScope(); resubmit(); } else throw e; }","preventionTips":["Never mix global-scope and cluster-scope mapping commands for the same topic.","Pin one scope convention per environment in tooling."],"tags":["rocketmq","broker","topic-queue-mapping","static-topic","scope","controller","metadata"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}