apache/rocketmq · error · MQClientException

subscription is null

Error message

subscription is null

What it means

checkConfig() requires the subscription map to be non-null. subscribe() populates it, so this fires when start() is called before any subscribe() — the consumer has nothing to consume and the client refuses to start with a null subscription table.

Source

Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java:1076

        Date dt = UtilAll.parseDate(this.defaultMQPushConsumer.getConsumeTimestamp(), UtilAll.YYYYMMDDHHMMSS);
        if (null == dt) {
            throw new MQClientException(
                "consumeTimestamp is invalid, the valid format is yyyyMMddHHmmss,but received "
                    + this.defaultMQPushConsumer.getConsumeTimestamp()
                    + " " + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), null);
        }

        // 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"

View on GitHub (pinned to 293f588571)

Solutions

  1. Call consumer.subscribe(topic, "*") (or an SQL92/tag expression) before start()
  2. If topics come from a list, fail loudly when the list is empty instead of starting with nothing
  3. Keep subscribe-before-start ordering in your consumer factory method

Example fix

// before
DefaultMQPushConsumer c = new DefaultMQPushConsumer("g");
c.setMessageListener(...);
c.start(); // no subscribe() -> subscription is null

// after
c.subscribe("order-topic", "*");
c.setMessageListener(...);
c.start();
Defensive patterns

Strategy: validation

Validate before calling

if (topics == null || topics.isEmpty())
    throw new IllegalArgumentException("At least one topic required");
for (String t : topics) consumer.subscribe(t, "*");
consumer.start();

Prevention

When it happens

Trigger: Calling consumer.start() without ever calling consumer.subscribe(topic, subExpression); code that clears subscriptions (getSubscription().clear()) before start; conditional subscription logic that skips all subscribe calls on some path.

Common situations: Forgetting subscribe() in quick-start code; per-environment wiring where the topic list is empty in one environment so the subscribe loop never runs.

Related errors


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