apache/rocketmq · error · MQClientException
executor rejected
Error message
executor rejected
What it means
MQClientException thrown from the async-send path when executor.submit(runnable) raises RejectedExecutionException and backpressure is disabled. The default async executor has a bounded queue; once the in-flight async sends exceed it, the JDK executor rejects the task and RocketMQ rethrows it as this error. When enableBackpressureForAsyncMode is true the rejection is instead absorbed by running the task on the caller thread (natural backpressure).
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java:679
costTime = System.currentTimeMillis() - beginStartTime;
isSemaphoreAsyncSizeAcquired = timeout - costTime > 0
&& semaphoreAsyncSendSize.tryAcquire(msgLen, timeout - costTime, TimeUnit.MILLISECONDS);
sendCallback.isSemaphoreAsyncSizeAcquired = isSemaphoreAsyncSizeAcquired;
defaultMQProducer.releaseBackPressureForAsyncSendSizeLock();
if (!isSemaphoreAsyncSizeAcquired) {
sendCallback.onException(
new RemotingTooMuchRequestException("send message tryAcquire semaphoreAsyncSize timeout"));
return;
}
}
executor.submit(runnable);
} catch (RejectedExecutionException e) {
if (isEnableBackpressureForAsyncMode) {
runnable.run();
} else {
throw new MQClientException("executor rejected ", e);
}
}
}
public MessageQueue invokeMessageQueueSelector(Message msg, MessageQueueSelector selector, Object arg,
final long timeout) throws MQClientException, RemotingTooMuchRequestException {
long beginStartTime = System.currentTimeMillis();
this.makeSureStateOK();
Validators.checkMessage(msg, this.defaultMQProducer);
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());View on GitHub (pinned to 293f588571)
Solutions
- Enable backpressure so rejection degrades to caller-thread execution: producer.setEnableBackpressureForAsyncMode(true) (and tune backpressureForAsyncFlushTimeout if needed)
- Increase the async executor queue capacity via producer.setAsyncExecutorSizeConfig(...) / defaultAsyncExecutorQueueSize to match peak throughput
- Rate-limit or batch sends at the application layer (semaphore, Resilience4j bulkhead) so in-flight async sends stay under the queue bound
- Ensure SendCallback implementations return quickly; offload heavy work to a separate executor
Example fix
// before producer.setEnableBackpressureForAsyncMode(false); producer.send(msg, callback); // burst -> executor rejected // after producer.setEnableBackpressureForAsyncMode(true); producer.send(msg, callback); // overflow runs on caller thread instead of throwing
Defensive patterns
Strategy: fallback
Validate before calling
producer.setEnableBackpressureForAsyncMode(true); // rejection degrades to caller-thread run // optional: size the executor for peak throughput producer.getDefaultMQProducerImpl()... // or set asyncExecutorSizeConfig queue size >= peak in-flight sends
Try / catch
producer.send(msg, new SendCallback() {
public void onSuccess(SendResult r) { ... }
public void onException(Throwable e) {
if (e instanceof MQClientException && String.valueOf(e.getMessage()).contains("executor rejected")) {
localBuffer.offer(msg); // fallback: spool and retry later
}
}
}); Prevention
- Enable enableBackpressureForAsyncMode in high-throughput async producers
- Bound in-flight async sends with an application-side semaphore (e.g. Semaphore(N)) before calling send
- Size the async executor queue from load tests (peak RPS * worst-case latency)
- Keep SendCallback bodies fast; offload heavy processing to another pool
When it happens
Trigger: triggerScenarios
Common situations: See trigger scenarios.
Related errors
- sendMessage call timeout
- 13
- Sending message to topic[%s] is forbidden.
- consumeThreadMin Out of range [1, 1000]
- consumeThreadMax Out of range [1, 1000]
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/79b51e655e9ab0da.
Report an issue: GitHub.