apache/rocketmq · error · MQClientException
messageListener must be instanceof MessageListenerOrderly or
Error message
messageListener must be instanceof MessageListenerOrderly or MessageListenerConcurrently
What it means
checkConfig() accepts only MessageListenerOrderly or MessageListenerConcurrently as the listener type (checked via instanceof after the null check). Any other MessageListener implementation (the base interface has others, e.g. MessageListenerOrderly/Concurrently are the supported concrete contracts) is rejected because the push consumer's dispatch machinery only implements these two protocols.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java:1093
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(
"consumeThreadMin Out of range [1, 1000]"
+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),
null);
}
// consumeThreadMax
if (this.defaultMQPushConsumer.getConsumeThreadMax() < 1 || this.defaultMQPushConsumer.getConsumeThreadMax() > 1000) {
throw new MQClientException(
"consumeThreadMax Out of range [1, 1000]"View on GitHub (pinned to 293f588571)
Solutions
- Implement MessageListenerConcurrently (default choice) or MessageListenerOrderly (for ordered consumption with queue-level locking)
- If you wrote a custom interface, wrap it in an adapter class implementing one of the two supported listeners
- Use the exact lambdas: (MessageListenerConcurrently) or (MessageListenerOrderly) casts so the compiler targets the right interface
Example fix
// before
class MyListener implements MessageListener { ... } // base interface only
c.registerMessageListener(new MyListener()); // rejected
// after
class MyListener implements MessageListenerConcurrently {
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext ctx) { ... return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; }
}
c.registerMessageListener(new MyListener()); Defensive patterns
Strategy: type-guard
Validate before calling
Objects.requireNonNull(listener, "listener required");
if (!(listener instanceof MessageListenerConcurrently) && !(listener instanceof MessageListenerOrderly))
throw new IllegalArgumentException("Listener must be MessageListenerConcurrently or MessageListenerOrderly");
consumer.registerMessageListener(listener); Type guard
boolean isSupportedListener(MessageListener l) {
return l instanceof MessageListenerConcurrently || l instanceof MessageListenerOrderly;
} Prevention
- Implement one of the two supported interfaces; never the bare MessageListener
- When using lambdas, cast explicitly: (MessageListenerConcurrently) (msgs, ctx) -> ...
- Wrap custom listener logic in an adapter of the supported types
When it happens
Trigger: Passing a listener that implements only the base org.apache.rocketmq.client.consumer.listener.MessageListener interface; passing a custom subinterface; passing a lambdas targeted at an unsupported functional interface.
Common situations: Implementing the generic interface 'to be flexible'; upgrading from old client versions where listener handling differed; mocking MessageListener in tests.
Related errors
- messageListener is null
- lite subscription quota exceeded
- consumerGroup can not equal
- messageModel is null
- allocateMessageQueueStrategy is null
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/e54c701007bd5b4c.
Report an issue: GitHub.