alibaba/spring-cloud-alibaba · warning · MessagingException
DefaultMQPushConsumer consuming failed, Caused by messageExt
Error message
DefaultMQPushConsumer consuming failed, Caused by messageExtList is empty
What it means
A defensive guard in consumeMessage: RocketMQ delivered an empty message batch, which the adapter cannot iterate. Rather than silently no-op, it throws MessagingException. In practice this indicates a client-side or batching anomaly rather than a normal empty-poll (the pull consumer returns null instead).
Source
Thrown at spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java:137
"DefaultMQPushConsumer init failed, Caused by " + e.getMessage())
.build(), e);
}
}
/**
* The actual execution of a user-defined input consumption service method.
* @param messageExtList rocket mq message list
* @param failSupplier {@link ConsumeConcurrentlyStatus} or
* {@link ConsumeOrderlyStatus}
* @param sucSupplier {@link ConsumeConcurrentlyStatus} or
* {@link ConsumeOrderlyStatus}
* @param <R> object
* @return R
*/
private <R> R consumeMessage(List<MessageExt> messageExtList,
Supplier<R> failSupplier, Supplier<R> sucSupplier) {
if (CollectionUtils.isEmpty(messageExtList)) {
throw new MessagingException(
"DefaultMQPushConsumer consuming failed, Caused by messageExtList is empty");
}
// With consumeMessageBatchMaxSize > 1, a recoveryCallback that throws midway
// through a batch causes the whole batch to be redelivered, so previously
// recovered messages will be recovered again. Prefer batchSize=1 when relying
// on recoveryCallback for DLQ wiring.
for (MessageExt messageExt : messageExtList) {
try {
Message<?> message = RocketMQMessageConverterSupport
.convertMessage2Spring(messageExt);
if (this.retryTemplate != null) {
try {
this.retryTemplate.execute(() -> {
this.sendMessage(message);
return Boolean.TRUE;
});
}
catch (RetryException retryException) {View on GitHub (pinned to 115d590110)
Solutions
- If you have a custom listener adapter, filter empty lists before delegating to consumeMessage.
- Ensure `consumeMessageBatchMaxSize` is a sane positive value (the code prefers 1 when relying on recoveryCallback).
- Upgrade the RocketMQ client to match the broker version if empty batches recur.
Example fix
// before
adapter.consumeMessage(msgs, failSupplier, sucSupplier);
// after
if (CollectionUtils.isEmpty(msgs)) {
return sucSupplier.get(); // tolerate empty batch
}
adapter.consumeMessage(msgs, failSupplier, sucSupplier); Defensive patterns
Strategy: validation
Validate before calling
// Never hand an empty batch to the consumer path.
if (!CollectionUtils.isEmpty(msgs)) {
consumeMessage(msgs, failSupplier, sucSupplier);
} Prevention
- Guard against empty/null batches at the listener boundary.
- Prefer batchSize=1 when using recoveryCallback/DLQ wiring.
- Keep RocketMQ client and broker versions aligned.
When it happens
Trigger: The push MessageListener/consume path calls consumeMessage with an empty or null `messageExtList`.
Common situations: Misconfigured `consumeMessageBatchMaxSize`; a custom listener that manually forwards an empty list; broker/client version mismatch producing zero-length batches; the recoveryCallback path mishandling batches.
Related errors
- group must be configured for DLQ{destination.getName()}
- group must be configured for DLQ{topic}
- DefaultMQPushConsumer init failed, Caused by {e.getMessage()
- DefaultMQPushConsumer not initialized
- Already acknowledged
AI-assisted analysis of alibaba/spring-cloud-alibaba@115d590110 (2026-08-14).
Data as JSON: /api/errors/6451bb6695fb43ba.
Report an issue: GitHub.