apache/rocketmq · error · MQClientException
messageListener is null
Error message
messageListener is null
What it means
checkConfig() requires a message listener before start. The listener is the callback that receives messages; without it the push consumer cannot deliver, so startup is rejected when getMessageListener() returns null.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java:1084
// allocateMessageQueueStrategy
if (null == this.defaultMQPushConsumer.getAllocateMessageQueueStrategy()) {
throw new MQClientException(
"allocateMessageQueueStrategy is null"
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),
null);
}
// subscription
if (null == this.defaultMQPushConsumer.getSubscription()) {
throw new MQClientException(
"subscription is null"
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),
null);
}
// messageListener
if (null == this.defaultMQPushConsumer.getMessageListener()) {
throw new MQClientException(
"messageListener is null"
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),
null);
}
boolean orderly = this.defaultMQPushConsumer.getMessageListener() instanceof MessageListenerOrderly;
boolean concurrently = this.defaultMQPushConsumer.getMessageListener() instanceof MessageListenerConcurrently;
if (!orderly && !concurrently) {
throw new MQClientException(
"messageListener must be instanceof MessageListenerOrderly or MessageListenerConcurrently"
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),
null);
}
// consumeThreadMin
if (this.defaultMQPushConsumer.getConsumeThreadMin() < 1
|| this.defaultMQPushConsumer.getConsumeThreadMin() > 1000) {
throw new MQClientException(View on GitHub (pinned to 293f588571)
Solutions
- Call consumer.registerMessageListener(new MessageListenerConcurrently/Orderly(){...}) before start()
- If using Spring, verify the listener bean resolves (no null injection)
- Centralize consumer construction in one factory so subscribe + listener + start always happen together
Example fix
// before
DefaultMQPushConsumer c = new DefaultMQPushConsumer("g");
c.subscribe("t", "*");
c.start(); // no listener
// after
c.registerMessageListener((MessageListenerConcurrently) (msgs, ctx) -> ConsumeConcurrentlyStatus.CONSUME_SUCCESS);
c.start(); Defensive patterns
Strategy: validation
Validate before calling
Objects.requireNonNull(listener, "messageListener required"); consumer.registerMessageListener(listener);
Type guard
boolean isSupportedListener(Object l) {
return l instanceof MessageListenerConcurrently || l instanceof MessageListenerOrderly;
} Prevention
- Register the listener in the same factory method that subscribes and starts
- Verify DI listener beans resolve non-null at context startup
When it happens
Trigger: Calling start() without setMessageListener(...); registering the listener on a different consumer object than the one started (copy-paste bug); listener injection in DI returning null because the bean is missing.
Common situations: Quick-start code that forgets registerMessageListener; Spring configuration where the listener bean name is misspelled; refactoring that moved the listener setup behind a flag that is off.
Related errors
- consumerGroup can not equal
- Topic or listener is null
- consumerGroup is null
- messageModel is null
- consumeFromWhere is null
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/6e8531f36f4a3cbf.
Report an issue: GitHub.