apache/rocketmq · error · RemotingTooMuchRequestException

sendDefaultImpl call timeout

Error message

sendDefaultImpl call timeout

What it means

RemotingTooMuchRequestException thrown at the end of sendDefaultImpl when the total elapsed time since the call began already exceeds the send timeout (callTimeout flag set from a timeout-class failure) - i.e. all retry times plus broker communication consumed the budget, and the loop aborts rather than issuing another attempt whose remaining timeout would be negative. This is client-side deadline enforcement after at least one timeout-flavored failure, not a broker rejection.

Source

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

                } else {
                    break;
                }
            }

            if (sendResult != null) {
                return sendResult;
            }
            String info = String.format("Send [%d] times, still failed, cost [%d]ms, Topic: %s, BrokersSent: %s",
                times,
                System.currentTimeMillis() - beginTimestampFirst,
                msg.getTopic(),
                Arrays.toString(brokersSent));

            info += FAQUrl.suggestTodo(FAQUrl.SEND_MSG_FAILED);

            MQClientException mqClientException = new MQClientException(info, exception);
            if (callTimeout) {
                throw new RemotingTooMuchRequestException("sendDefaultImpl call timeout");
            }

            if (exception instanceof MQBrokerException) {
                mqClientException.setResponseCode(((MQBrokerException) exception).getResponseCode());
            } else if (exception instanceof RemotingConnectException) {
                mqClientException.setResponseCode(ClientErrorCode.CONNECT_BROKER_EXCEPTION);
            } else if (exception instanceof RemotingTimeoutException) {
                mqClientException.setResponseCode(ClientErrorCode.ACCESS_BROKER_TIMEOUT);
            } else if (exception instanceof MQClientException) {
                mqClientException.setResponseCode(ClientErrorCode.BROKER_NOT_EXIST_EXCEPTION);
            }

            throw mqClientException;
        }

        validateNameServerSetting();

        throw new MQClientException("No route info of this topic: " + msg.getTopic() + FAQUrl.suggestTodo(FAQUrl.NO_TOPIC_ROUTE_INFO),

View on GitHub (pinned to 293f588571)

Solutions

  1. Raise the budget: producer.setSendMsgTimeout(3000+) or pass a larger timeout to send(msg, timeout), and keep it >= (retries+1) * expected-RTT
  2. Reduce attempts: producer.setRetryTimesWhenSendFailed(0/1) for fast-fail paths, or setRetryAnotherBrokerWhenNotStoreOK(false) to avoid extra hops
  3. Investigate broker latency (broker flush disk type SYNC_FLUSH vs ASYNC_FLUSH, disk utilization, page cache) - if each attempt times out, timeouts only mask it
  4. For latency-critical traffic, send with explicit timeout per call and implement app-level fallback (queue locally / circuit break) instead of relying on long client retries

Example fix

// before
producer.setSendMsgTimeout(500); // < RTT of cross-region link
producer.send(msg);
// after
producer.setSendMsgTimeout(3_000);
producer.setRetryTimesWhenSendFailed(1);
producer.send(msg, 3_000);
Defensive patterns

Strategy: retry

Validate before calling

 // budget check before send: timeout must exceed (retries+1) * expected RTT
int retries = producer.getRetryTimesWhenSendFailed();
if (timeoutMs < (retries + 1) * expectedRttMs) {
    timeoutMs = (retries + 1) * expectedRttMs * 2;
}

Try / catch

RetrySchemas.exponential(3, Duration.ofMillis(500)).retryOn(
    RemotingTooMuchRequestException.class).execute(ctx -> producer.send(msg));
// only if the operation is idempotent or message has unique key for dedup

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/a17df52a609a662e. Report an issue: GitHub.