{"record":{"id":"b2b0190b209b7220","repo":"apache/rocketmq","slug":"subscribe-exception","errorCode":null,"errorMessage":"subscribe exception","messagePattern":"subscribe exception","errorType":"exception","errorClass":"MQClientException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java","lineNumber":523,"sourceCode":"            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            }\n        } catch (Exception e) {\n            throw new MQClientException(\"subscribe exception\", e);\n        }\n    }\n\n    public synchronized void subscribe(String topic, String subExpression) throws MQClientException {\n        try {\n            if (topic == null || \"\".equals(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 MessageQueueListenerImpl());\n            assignedMessageQueue.setRebalanceImpl(this.rebalanceImpl);\n            if (serviceState == ServiceState.RUNNING) {\n                this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();\n                updateTopicSubscribeInfoWhenSubscriptionChanged();\n            }\n        } catch (Exception e) {","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java#L505-L541","documentation":"MQClientException thrown by DefaultLitePullConsumerImpl.subscribe (both overloads) as a catch-all wrapper: any exception raised inside the try block while subscribing is rethrown with the generic message 'subscribe exception' and the original as cause. The most common real cause is FilterAPI.buildSubscriptionData rejecting an invalid subscription expression (bad SQL92/tag syntax), but any failure (including the empty-topic IllegalArgumentException) surfaces this way.","triggerScenarios":"subscribe(topic, \"TAGA || \") or malformed SQL92 like \"a between 1 and\" -> buildSubscriptionData throws; empty topic argument; unexpected runtime exceptions during listener wiring. The distinguishing detail lives in e.getCause().","commonSituations":"Typo'd tag expressions (unbalanced parentheses, bad operators); switching tag filter syntax to SQL92 without enabling sqlFilter support; dynamic expressions built from user input; null subExpression handled differently than expected.","solutions":["Always inspect e.getCause() — it names the actual broken input","Fix the subscription expression: valid tag syntax like \"TAGA || TAGB\", or valid SQL92 like \"a > 5 AND b IS NOT NULL\" with consumer experimental SQL filter enabled where required","Validate dynamic expressions before passing them to subscribe","Ensure topic/subExpression are non-null and topic non-empty"],"exampleFix":"// before\nconsumer.subscribe(\"T\", \"TAGA || \"); // trailing operator -> subscribe exception\n\n// after\ntry {\n    consumer.subscribe(\"T\", \"TAGA || TAGB\");\n} catch (MQClientException e) {\n    throw new IllegalArgumentException(\"Bad subscription: \" + e.getCause().getMessage(), e);\n}","handlingStrategy":"try-catch","validationCode":"// pre-validate a tag expression crudely before subscribing\nprivate boolean looksLikeTagExpr(String expr) {\n    return expr == null || \"*\".equals(expr) || expr.matches(\"[\\w ||]+\");\n}\nif (!looksLikeTagExpr(sub)) throw new IllegalArgumentException(\"bad sub expression: \" + sub);","typeGuard":null,"tryCatchPattern":"try {\n    consumer.subscribe(topic, subExpression);\n} catch (MQClientException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof MQClientException && cause.getMessage().contains(\"subscription\")) {\n        // invalid expression: fix and resubscribe\n    } else throw e;\n}","preventionTips":["Unwrap the cause: the generic wrapper hides the real validation error","Test subscription expressions with FilterAPI.buildSubscriptionData in unit tests before deploying","Keep tag syntax simple (\"TAGA || TAGB\") and enable SQL92 support only when used"],"tags":["rocketmq","subscribe","filter","consumer","wrapper"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}