apache/rocketmq · error · MQClientException

Broker[{destBrokerName}] master node does not exist

Error message

Broker[{destBrokerName}] master node does not exist

What it means

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.

Source

Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java:658

    public void updateConsumeOffsetToBroker(MessageQueue mq, long offset, boolean isOneway) throws RemotingException,
        MQBrokerException, InterruptedException, MQClientException {
        this.offsetStore.updateConsumeOffsetToBroker(mq, offset, isOneway);
    }

    @Deprecated
    public void sendMessageBack(MessageExt msg, int delayLevel, final String brokerName, String consumerGroup)
        throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
        try {
            String destBrokerName = brokerName;
            if (destBrokerName != null && destBrokerName.startsWith(MixAll.LOGICAL_QUEUE_MOCK_BROKER_PREFIX)) {
                destBrokerName = this.mQClientFactory.getBrokerNameFromMessageQueue(this.defaultMQPullConsumer.queueWithNamespace(new MessageQueue(msg.getTopic(), msg.getBrokerName(), msg.getQueueId())));
            }
            String brokerAddr = (null != destBrokerName) ? this.mQClientFactory.findBrokerAddressInPublish(destBrokerName)
                : RemotingHelper.parseSocketAddressAddr(msg.getStoreHost());

            if (UtilAll.isBlank(brokerAddr)) {
                throw new MQClientException("Broker[" + destBrokerName + "] master node does not exist", null);
            }

            if (UtilAll.isBlank(consumerGroup)) {
                consumerGroup = this.defaultMQPullConsumer.getConsumerGroup();
            }

            this.mQClientFactory.getMQClientAPIImpl().consumerSendMessageBack(brokerAddr, brokerName, msg, consumerGroup,
                delayLevel, 3000, this.defaultMQPullConsumer.getMaxReconsumeTimes());
        } catch (Exception e) {
            log.error("sendMessageBack Exception, " + this.defaultMQPullConsumer.getConsumerGroup(), e);

            Message newMsg = new Message(MixAll.getRetryTopic(this.defaultMQPullConsumer.getConsumerGroup()), msg.getBody());
            String originMsgId = MessageAccessor.getOriginMessageId(msg);
            MessageAccessor.setOriginMessageId(newMsg, UtilAll.isBlank(originMsgId) ? msg.getMsgId() : originMsgId);
            newMsg.setFlag(msg.getFlag());
            MessageAccessor.setProperties(newMsg, msg.getProperties());
            MessageAccessor.putProperty(newMsg, MessageConst.PROPERTY_RETRY_TOPIC, msg.getTopic());
            MessageAccessor.setReconsumeTime(newMsg, String.valueOf(msg.getReconsumeTimes() + 1));

View on GitHub (pinned to 293f588571)

Solutions

  1. Retry after refreshing routes: consumer.getDefaultMQPullConsumerImpl() internals aside, call updateTopicRouteInfoFromNameServer indirectly by retrying the operation after a short delay
  2. Check nameserver connectivity (namesrvAddr) so the route table keeps a current master for the broker
  3. Verify the target broker is RUNNING (not in maintenance) via broker admin status or dashboard
  4. 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

Example fix

// before
consumer.getDefaultMQPullConsumerImpl().sendMessageBack(msg, 3, "broker-a", group); // fails if route stale

// after
// refresh route then retry
for (int i = 0; i < 3; i++) {
    try {
        impl.sendMessageBack(msg, 3, "broker-a", group);
        break;
    } catch (MQClientException e) {
        Thread.sleep(1000L << i); // wait for route refresh
    }
}
Defensive patterns

Strategy: retry

Validate before calling

String addr = consumer.fetchMessageQueues(topic) != null ? "route-ok" : null; // indirect route check
if (addr == null) { /* refresh/wait before sendMessageBack */ }

Try / catch

catch (MQClientException e) { if (e.getMessage().contains("master node does not exist")) { sleepBackoff(); retryWithLimit(); } else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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