apache/rocketmq · error · RemotingTooMuchRequestException

sendSelectImpl call timeout

Error message

sendSelectImpl call timeout

What it means

RemotingTooMuchRequestException thrown from invokeMessageQueueSelector when the elapsed time from method entry to just before sending (state check, message validation, topic-route lookup, and selector execution) already exceeds the configured timeout. No network call has necessarily failed - the client is enforcing its own deadline: spending the whole budget locally means the remaining timeout passed to sendKernelImpl would be <= 0.

Source

Thrown at client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java:707

        TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic());
        if (topicPublishInfo != null && topicPublishInfo.ok()) {
            MessageQueue mq = null;
            try {
                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) {

View on GitHub (pinned to 293f588571)

Solutions

  1. Increase the timeout passed to send(msg, selector, arg, timeout) or producer.setSendMsgTimeout(...) to cover route lookup + selector + network send
  2. Warm the route cache at startup by pre-calling fetchPublishMessageQueues or setting a topicPublishInfo before the first timed request
  3. Move slow logic out of MessageQueueSelector.select - it runs inside the timeout window; precompute the shard key and use a cheap selector
  4. Measure with beginStartTime cost logging to confirm where the budget goes before raising the timeout

Example fix

// before
producer.send(msg, selector, key, 100L); // route lookup alone takes ~150ms
// after
producer.setSendMsgTimeout(3_000);
producer.send(msg, selector, key, 3_000L);
Defensive patterns

Strategy: validation

Validate before calling

 long t0 = System.currentTimeMillis();
// warm route cache before timed sends
producer.fetchPublishMessageQueues(topic);
// budget = warm path cost + network RTT
long budget = Math.max(defaultTimeout, (System.currentTimeMillis() - t0) + expectedRttMs * 2);

Try / catch

try {
    producer.send(msg, selector, arg, timeout);
} catch (RemotingTooMuchRequestException e) { // client-side deadline, no RPC sent or budget exhausted
    retryWithLargerBudget(msg, selector, arg, timeout * 2);
}

Prevention

When it happens

Trigger: triggerScenarios

Common situations: commonSituations

Understand the failure class

Related errors


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