apache/rocketmq · error · MQClientException

Topic or listener is null

Error message

Topic or listener is null

What it means

DefaultLitePullConsumerImpl.registerTopicMessageQueueChangeListener(topic, listener) throws MQClientException("Topic or listener is null") when either argument is null. The listener is invoked when the queue count of a topic changes (scale-up/scale-down), and the API stores it keyed by topic, so both are mandatory.

Source

Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java:1270

            return false;
        }

        for (MessageQueue messageQueue : set2) {
            if (!set1.contains(messageQueue)) {
                return false;
            }
        }
        return true;
    }

    public AssignedMessageQueue getAssignedMessageQueue() {
        return assignedMessageQueue;
    }

    public synchronized void registerTopicMessageQueueChangeListener(String topic,
        TopicMessageQueueChangeListener listener) throws MQClientException {
        if (topic == null || listener == null) {
            throw new MQClientException("Topic or listener is null", null);
        }
        if (topicMessageQueueChangeListenerMap.containsKey(topic)) {
            log.warn("Topic {} had been registered, new listener will overwrite the old one", topic);
        }
        topicMessageQueueChangeListenerMap.put(topic, listener);
        if (this.serviceState == ServiceState.RUNNING) {
            Set<MessageQueue> messageQueues = fetchMessageQueues(topic);
            messageQueuesForTopic.put(topic, messageQueues);
        }
    }

    private Set<MessageQueue> parseMessageQueues(Set<MessageQueue> queueSet) {
        Set<MessageQueue> resultQueues = new HashSet<>();
        for (MessageQueue messageQueue : queueSet) {
            String userTopic = NamespaceUtil.withoutNamespace(messageQueue.getTopic(),
                this.defaultLitePullConsumer.getNamespace());
            resultQueues.add(new MessageQueue(userTopic, messageQueue.getBrokerName(), messageQueue.getQueueId()));
        }

View on GitHub (pinned to 293f588571)

Solutions

  1. Null-check both arguments and skip or fail registration with a clear message
  2. Provide a no-op listener implementation instead of null when you only need the side effects elsewhere

Example fix

// before
consumer.registerTopicMessageQueueChangeListener(topic, listenerOrNull);

// after
if (topic != null && listenerOrNull != null) {
    consumer.registerTopicMessageQueueChangeListener(topic, listenerOrNull);
}
Defensive patterns

Strategy: validation

Validate before calling

if (topic != null && listener != null) {
    consumer.registerTopicMessageQueueChangeListener(topic, listener);
}

Prevention

When it happens

Trigger: registerTopicMessageQueueChangeListener(topic, null); passing a listener built conditionally that stayed null; registering before the topic string was resolved.

Common situations: Optional listeners wired via DI that were not configured; registering for a topic name that failed env substitution.

Related errors


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