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

  1. Call consumer.registerMessageListener(new MessageListenerConcurrently/Orderly(){...}) before start()
  2. If using Spring, verify the listener bean resolves (no null injection)
  3. 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

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


AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14). Data as JSON: /api/errors/6e8531f36f4a3cbf. Report an issue: GitHub.