apache/rocketmq · error · MQClientException
select message queue return null.
Error message
select message queue return null.
What it means
MQClientException thrown from invokeMessageQueueSelector when the MessageQueueSelector.select(...) completes without throwing but returns null (the client also null-checks the namespace-wrapped result). A null selection cannot be mapped to a broker queue, so the send-select call aborts before any network I/O. Distinct from error 267: here the selector ran cleanly but produced no queue.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java:712
List<MessageQueue> messageQueueList =
mQClientFactory.getMQAdminImpl().parsePublishMessageQueues(topicPublishInfo.getMessageQueueList());
Message userMessage = MessageAccessor.cloneMessage(msg);
String userTopic = NamespaceUtil.withoutNamespace(userMessage.getTopic(), mQClientFactory.getClientConfig().getNamespace());
userMessage.setTopic(userTopic);
mq = mQClientFactory.getClientConfig().queueWithNamespace(selector.select(messageQueueList, userMessage, arg));
} catch (Throwable e) {
throw new MQClientException("select message queue threw exception.", e);
}
long costTime = System.currentTimeMillis() - beginStartTime;
if (timeout < costTime) {
throw new RemotingTooMuchRequestException("sendSelectImpl call timeout");
}
if (mq != null) {
return mq;
} else {
throw new MQClientException("select message queue return null.", null);
}
}
validateNameServerSetting();
throw new MQClientException("No route info for this topic, " + msg.getTopic(), null);
}
public MessageQueue selectOneMessageQueue(final TopicPublishInfo tpInfo, final String lastBrokerName, final boolean resetIndex) {
return this.mqFaultStrategy.selectOneMessageQueue(tpInfo, lastBrokerName, resetIndex);
}
public void updateFaultItem(final String brokerName, final long currentLatency, boolean isolation,
boolean reachable) {
this.mqFaultStrategy.updateFaultItem(brokerName, currentLatency, isolation, reachable);
}
private void validateNameServerSetting() throws MQClientException {
List<String> nsList = this.getMqClientFactory().getMQClientAPIImpl().getNameServerAddressList();View on GitHub (pinned to 293f588571)
Solutions
- Make the selector always return a concrete queue; fall back to a default strategy (round-robin index or mqs.get(0)) instead of null
- If the lookup can legitimately miss, seed/initialize the mapping before returning or fall back to a hash of the message key
- Handle the empty-mqs case explicitly (throw a descriptive exception or pick queue 0) rather than letting the lambda fall through to null
- Add a unit test asserting select() never returns null for all expected inputs
Example fix
// before
MessageQueueSelector s = (mqs, m, arg) -> keyQueueMap.get(arg); // null on miss
// after
MessageQueueSelector s = (mqs, m, arg) -> {
MessageQueue mq = keyQueueMap.get(arg);
return mq != null ? mq : mqs.get((arg.hashCode() & Integer.MAX_VALUE) % mqs.size());
}; Defensive patterns
Strategy: validation
Validate before calling
MessageQueueSelector nonNull = (mqs, m, arg) -> {
MessageQueue q = rawSelector.select(mqs, m, arg);
return q != null ? q : mqs.get(ThreadLocalRandom.current().nextInt(mqs.size()));
}; Type guard
boolean selectsQueue(MessageQueueSelector s, List<MessageQueue> mqs, Message m, Object arg) {
return s.select(mqs, m, arg) != null; // for pre-flight checks in tests
} Try / catch
try {
producer.send(msg, selector, arg);
} catch (MQClientException e) {
if ("select message queue return null.".equals(e.getMessage())) {
producer.send(msg); // fallback: default send-path selection
} else throw e;
} Prevention
- Always give selectors a terminal fallback branch (round-robin or hash)
- Avoid map.get(...)/Optional.orElse(null) as the return expression of select()
- Assert non-null return in selector unit tests for every input class
When it happens
Trigger: triggerScenarios
Common situations: commonSituations
Related errors
- select message queue threw exception.
- sendSelectImpl call timeout
- 13
- Sending message to topic[%s] is forbidden.
- sendMessage call timeout
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/be73737e26da8319.
Report an issue: GitHub.