{"record":{"id":"c680ef6e59617f7b","repo":"apache/rocketmq","slug":"broker-destbrokername-master-node-does-not-exis","errorCode":null,"errorMessage":"Broker[{destBrokerName}] master node does not exist","messagePattern":"Broker\\[(.+?)\\] master node does not exist","errorType":"exception","errorClass":"MQClientException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java","lineNumber":658,"sourceCode":"\n    public void updateConsumeOffsetToBroker(MessageQueue mq, long offset, boolean isOneway) throws RemotingException,\n        MQBrokerException, InterruptedException, MQClientException {\n        this.offsetStore.updateConsumeOffsetToBroker(mq, offset, isOneway);\n    }\n\n    @Deprecated\n    public void sendMessageBack(MessageExt msg, int delayLevel, final String brokerName, String consumerGroup)\n        throws RemotingException, MQBrokerException, InterruptedException, MQClientException {\n        try {\n            String destBrokerName = brokerName;\n            if (destBrokerName != null && destBrokerName.startsWith(MixAll.LOGICAL_QUEUE_MOCK_BROKER_PREFIX)) {\n                destBrokerName = this.mQClientFactory.getBrokerNameFromMessageQueue(this.defaultMQPullConsumer.queueWithNamespace(new MessageQueue(msg.getTopic(), msg.getBrokerName(), msg.getQueueId())));\n            }\n            String brokerAddr = (null != destBrokerName) ? this.mQClientFactory.findBrokerAddressInPublish(destBrokerName)\n                : RemotingHelper.parseSocketAddressAddr(msg.getStoreHost());\n\n            if (UtilAll.isBlank(brokerAddr)) {\n                throw new MQClientException(\"Broker[\" + destBrokerName + \"] master node does not exist\", null);\n            }\n\n            if (UtilAll.isBlank(consumerGroup)) {\n                consumerGroup = this.defaultMQPullConsumer.getConsumerGroup();\n            }\n\n            this.mQClientFactory.getMQClientAPIImpl().consumerSendMessageBack(brokerAddr, brokerName, msg, consumerGroup,\n                delayLevel, 3000, this.defaultMQPullConsumer.getMaxReconsumeTimes());\n        } catch (Exception e) {\n            log.error(\"sendMessageBack Exception, \" + this.defaultMQPullConsumer.getConsumerGroup(), e);\n\n            Message newMsg = new Message(MixAll.getRetryTopic(this.defaultMQPullConsumer.getConsumerGroup()), msg.getBody());\n            String originMsgId = MessageAccessor.getOriginMessageId(msg);\n            MessageAccessor.setOriginMessageId(newMsg, UtilAll.isBlank(originMsgId) ? msg.getMsgId() : originMsgId);\n            newMsg.setFlag(msg.getFlag());\n            MessageAccessor.setProperties(newMsg, msg.getProperties());\n            MessageAccessor.putProperty(newMsg, MessageConst.PROPERTY_RETRY_TOPIC, msg.getTopic());\n            MessageAccessor.setReconsumeTime(newMsg, String.valueOf(msg.getReconsumeTimes() + 1));","sourceCodeStart":640,"sourceCodeEnd":676,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java#L640-L676","documentation":"Thrown by sendMessageBack when no master broker address can be resolved for the target broker. The method maps the (possibly logical-queue-mocked) broker name through findBrokerAddressInPublish or falls back to the message's storeHost; if both yield a blank address, the retry-message cannot be routed and the exception is raised.","triggerScenarios":"Calling sendMessageBack(msg, delayLevel, brokerName, consumerGroup) where brokerName has no live master in the client's route table (getTopicRouteInfo failed or is stale); the broker named in the message is down or in maintenance so only slaves are known; using logical queues (MixAll.LOGICAL_QUEUE_MOCK_BROKER_PREFIX) whose mapping cannot be resolved.","commonSituations":"Broker failover in progress while the client's route cache still points at the dead master; nameserver unreachable at retry time so findBrokerAddressInPublish returns null; heterogeneous deployment where the storeHost in the message is not reachable from the client network.","solutions":["Retry after refreshing routes: consumer.getDefaultMQPullConsumerImpl() internals aside, call updateTopicRouteInfoFromNameServer indirectly by retrying the operation after a short delay","Check nameserver connectivity (namesrvAddr) so the route table keeps a current master for the broker","Verify the target broker is RUNNING (not in maintenance) via broker admin status or dashboard","As the code itself does, fall back to building a retry message to the retry topic (the catch block already does this) — ensure that fallback path is reachable and its broker is up"],"exampleFix":"// before\nconsumer.getDefaultMQPullConsumerImpl().sendMessageBack(msg, 3, \"broker-a\", group); // fails if route stale\n\n// after\n// refresh route then retry\nfor (int i = 0; i < 3; i++) {\n    try {\n        impl.sendMessageBack(msg, 3, \"broker-a\", group);\n        break;\n    } catch (MQClientException e) {\n        Thread.sleep(1000L << i); // wait for route refresh\n    }\n}","handlingStrategy":"retry","validationCode":"String addr = consumer.fetchMessageQueues(topic) != null ? \"route-ok\" : null; // indirect route check\nif (addr == null) { /* refresh/wait before sendMessageBack */ }","typeGuard":null,"tryCatchPattern":"catch (MQClientException e) { if (e.getMessage().contains(\"master node does not exist\")) { sleepBackoff(); retryWithLimit(); } else throw e; }","preventionTips":["Keep nameserver address valid so route caches refresh","Wrap sendMessageBack in bounded retry with backoff","Monitor broker availability before issuing retry messages"],"tags":["rocketmq","pull-consumer","routing","broker-unavailable","retry-message"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}