{"record":{"id":"e34e85c7f55d67de","repo":"apache/rocketmq","slug":"topic-can-not-be-null-or-empty","errorCode":null,"errorMessage":"Topic can not be null or empty.","messagePattern":"Topic can not be null or empty\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java","lineNumber":503,"sourceCode":"                final String topic = entry.getKey();\n                this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic);\n            }\n        }\n    }\n\n    /**\n     * subscribe data by customizing messageQueueListener\n     *\n     * @param topic\n     * @param subExpression\n     * @param messageQueueListener\n     * @throws MQClientException\n     */\n    public synchronized void subscribe(String topic, String subExpression,\n        MessageQueueListener messageQueueListener) throws MQClientException {\n        try {\n            if (StringUtils.isEmpty(topic)) {\n                throw new IllegalArgumentException(\"Topic can not be null or empty.\");\n            }\n            setSubscriptionType(SubscriptionType.SUBSCRIBE);\n            SubscriptionData subscriptionData = FilterAPI.buildSubscriptionData(topic, subExpression);\n            this.rebalanceImpl.getSubscriptionInner().put(topic, subscriptionData);\n            this.defaultLitePullConsumer.setMessageQueueListener(new MessageQueueListener() {\n                @Override\n                public void messageQueueChanged(String topic, Set<MessageQueue> mqAll, Set<MessageQueue> mqDivided) {\n                    // First, update the assign queue\n                    updateAssignQueueAndStartPullTask(topic, mqAll, mqDivided);\n                    // run custom listener\n                    messageQueueListener.messageQueueChanged(topic, mqAll, mqDivided);\n                }\n            });\n            assignedMessageQueue.setRebalanceImpl(this.rebalanceImpl);\n            if (serviceState == ServiceState.RUNNING) {\n                this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();\n                updateTopicSubscribeInfoWhenSubscriptionChanged();\n            }","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java#L485-L521","documentation":"IllegalArgumentException (wrapped in MQClientException(\"subscribe exception\") by the enclosing catch) thrown by DefaultLitePullConsumerImpl.subscribe(topic, subExpression, listener) when topic is null or empty (StringUtils.isEmpty). It is a pure argument-validation failure raised before any subscription state changes.","triggerScenarios":"Calling consumer.subscribe(topic, \"*\", listener) with topic = null, \"\" or whitespace-driven empty strings from config; dynamic topic lists containing blank entries from split(\"\\n\") on user input.","commonSituations":"Property-driven topics where the key is misspelled so the value resolves to null; parsing topic lists where trailing separators produce empty entries; NPE-adjacent bugs where a lookup returns null and is passed straight through.","solutions":["Validate topics before subscribing: non-null and non-blank","Filter blank entries out of dynamic topic lists","Fix the config source supplying null/empty topic values","Fail fast at app startup with a clear message listing which topic was invalid"],"exampleFix":"// before\nfor (String t : topicsStr.split(\",\")) {\n    consumer.subscribe(t, \"*\"); // \"\" from trailing comma -> exception\n}\n\n// after\nfor (String t : topicsStr.split(\",\")) {\n    String topic = t.trim();\n    if (!topic.isEmpty()) {\n        consumer.subscribe(topic, \"*\");\n    }\n}","handlingStrategy":"validation","validationCode":"private void requireTopic(String t) {\n    if (t == null || t.trim().isEmpty()) throw new IllegalArgumentException(\"topic required\");\n}\nrequireTopic(topic);\nconsumer.subscribe(topic, \"*\", listener);","typeGuard":null,"tryCatchPattern":"try {\n    consumer.subscribe(topic, \"*\", listener);\n} catch (MQClientException e) {\n    if (e.getCause() instanceof IllegalArgumentException) { /* bad topic: fix input */ }\n    else throw e;\n}","preventionTips":["Trim and validate dynamic topic lists before subscribing","Guard config lookups that can return null topics","Log the offending topic value at the call site"],"tags":["rocketmq","validation","consumer","subscribe","topic"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}