{"record":{"id":"f2fd197d8ebc49a4","repo":"apache/rocketmq","slug":"topic-or-listener-is-null","errorCode":null,"errorMessage":"Topic or listener is null","messagePattern":"Topic or listener is null","errorType":"exception","errorClass":"MQClientException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java","lineNumber":1270,"sourceCode":"            return false;\n        }\n\n        for (MessageQueue messageQueue : set2) {\n            if (!set1.contains(messageQueue)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    public AssignedMessageQueue getAssignedMessageQueue() {\n        return assignedMessageQueue;\n    }\n\n    public synchronized void registerTopicMessageQueueChangeListener(String topic,\n        TopicMessageQueueChangeListener listener) throws MQClientException {\n        if (topic == null || listener == null) {\n            throw new MQClientException(\"Topic or listener is null\", null);\n        }\n        if (topicMessageQueueChangeListenerMap.containsKey(topic)) {\n            log.warn(\"Topic {} had been registered, new listener will overwrite the old one\", topic);\n        }\n        topicMessageQueueChangeListenerMap.put(topic, listener);\n        if (this.serviceState == ServiceState.RUNNING) {\n            Set<MessageQueue> messageQueues = fetchMessageQueues(topic);\n            messageQueuesForTopic.put(topic, messageQueues);\n        }\n    }\n\n    private Set<MessageQueue> parseMessageQueues(Set<MessageQueue> queueSet) {\n        Set<MessageQueue> resultQueues = new HashSet<>();\n        for (MessageQueue messageQueue : queueSet) {\n            String userTopic = NamespaceUtil.withoutNamespace(messageQueue.getTopic(),\n                this.defaultLitePullConsumer.getNamespace());\n            resultQueues.add(new MessageQueue(userTopic, messageQueue.getBrokerName(), messageQueue.getQueueId()));\n        }","sourceCodeStart":1252,"sourceCodeEnd":1288,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java#L1252-L1288","documentation":"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.","triggerScenarios":"registerTopicMessageQueueChangeListener(topic, null); passing a listener built conditionally that stayed null; registering before the topic string was resolved.","commonSituations":"Optional listeners wired via DI that were not configured; registering for a topic name that failed env substitution.","solutions":["Null-check both arguments and skip or fail registration with a clear message","Provide a no-op listener implementation instead of null when you only need the side effects elsewhere"],"exampleFix":"// before\nconsumer.registerTopicMessageQueueChangeListener(topic, listenerOrNull);\n\n// after\nif (topic != null && listenerOrNull != null) {\n    consumer.registerTopicMessageQueueChangeListener(topic, listenerOrNull);\n}","handlingStrategy":"validation","validationCode":"if (topic != null && listener != null) {\n    consumer.registerTopicMessageQueueChangeListener(topic, listener);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make the listener a required bean in DI wiring","Register listeners in the same place topics are configured"],"tags":["rocketmq","consumer","listener","validation"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}