{"record":{"id":"03deece932a02e58","repo":"apache/rocketmq","slug":"sendkernelimpl-call-timeout","errorCode":null,"errorMessage":"sendKernelImpl call timeout","messagePattern":"sendKernelImpl call timeout","errorType":"exception","errorClass":"RemotingTooMuchRequestException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java","lineNumber":1045,"sourceCode":"                            //If msg body was compressed, msgbody should be reset using prevBody.\n                            //Clone new message using compressed message body and recover origin massage.\n                            //Fix bug:https://github.com/apache/rocketmq-externals/issues/66\n                            tmpMessage = MessageAccessor.cloneMessage(msg);\n                            messageCloned = true;\n                            msg.setBody(prevBody);\n                        }\n\n                        if (topicWithNamespace) {\n                            if (!messageCloned) {\n                                tmpMessage = MessageAccessor.cloneMessage(msg);\n                                messageCloned = true;\n                            }\n                            msg.setTopic(NamespaceUtil.withoutNamespace(msg.getTopic(), this.defaultMQProducer.getNamespace()));\n                        }\n\n                        long costTimeAsync = System.currentTimeMillis() - beginStartTime;\n                        if (timeout < costTimeAsync) {\n                            throw new RemotingTooMuchRequestException(\"sendKernelImpl call timeout\");\n                        }\n                        sendResult = this.mQClientFactory.getMQClientAPIImpl().sendMessage(\n                            brokerAddr,\n                            brokerName,\n                            tmpMessage,\n                            requestHeader,\n                            timeout - costTimeAsync,\n                            communicationMode,\n                            sendCallback,\n                            topicPublishInfo,\n                            this.mQClientFactory,\n                            this.defaultMQProducer.getRetryTimesWhenSendAsyncFailed(),\n                            context,\n                            this);\n                        break;\n                    case ONEWAY:\n                    case SYNC:\n                        long costTimeSync = System.currentTimeMillis() - beginStartTime;","sourceCodeStart":1027,"sourceCodeEnd":1063,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java#L1027-L1063","documentation":"RemotingTooMuchRequestException thrown in sendKernelImpl's ASYNC branch: before delegating to sendMessage, the client computes costTimeAsync = now - beginStartTime (which starts back in sendDefaultImpl/send with callback, covering route lookup, selector, and per-attempt overhead) and if it already meets/exceeds the total timeout, it aborts instead of issuing the RPC with a non-positive remaining timeout. Pure client-side deadline check on the async path.","triggerScenarios":"triggerScenarios","commonSituations":"commonSituations","solutions":["Increase async send timeout (setSendMsgTimeout or the per-call timeout) so retries fit inside the budget","Warm route caches at startup (fetchPublishMessageQueues for hot topics) to remove first-send lookup cost","Reduce retryTimesWhenSendAsyncFailed or set sendMsgTimeout accounting for (retries+1)*worst-case attempt time","Handle RemotingTooMuchRequestException in the SendCallback by falling back to local queueing/dead-letter rather than dropping"],"exampleFix":"// before\nproducer.setSendMsgTimeout(300);\nproducer.send(msg, callback); // retries consume budget -> timeout\n// after\nproducer.setSendMsgTimeout(3_000);\nproducer.setRetryTimesWhenSendAsyncFailed(1);\nproducer.send(msg, callback);","handlingStrategy":"retry","validationCode":" producer.setSendMsgTimeout(Math.max(producer.getSendMsgTimeout(),\n    (producer.getRetryTimesWhenSendAsyncFailed() + 1) * expectedRttMs * 2));\nproducer.fetchPublishMessageQueues(topic); // warm route cache","typeGuard":null,"tryCatchPattern":"producer.send(msg, new SendCallback() {\n    public void onSuccess(SendResult r) { ack(); }\n    public void onException(Throwable e) {\n        if (e instanceof RemotingTooMuchRequestException) spoolAndRetryLater(msg); // deadline, not broker rejection\n        else log.error(\"send failed\", e);\n    }\n});","preventionTips":["Warm route caches before serving traffic","Budget async timeout for (asyncRetries+1) attempts","In SendCallback, distinguish RemotingTooMuchRequestException from broker errors - deadline expiry deserves spool/backoff, not immediate retry","Load-test async throughput to size executor and timeout together"],"tags":["rocketmq","producer","timeout","async-send"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}