{"record":{"id":"f30fcf56fffecc61","repo":"apache/rocketmq","slug":"subexpression-can-not-be-null-or-empty","errorCode":null,"errorMessage":"subExpression can not be null or empty.","messagePattern":"subExpression 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":589,"sourceCode":"        this.rebalanceImpl.getSubscriptionInner().remove(topic);\n        removePullTaskCallback(topic);\n        assignedMessageQueue.removeAssignedMessageQueue(topic);\n    }\n\n    public synchronized void assign(Collection<MessageQueue> messageQueues) {\n        if (messageQueues == null || messageQueues.isEmpty()) {\n            throw new IllegalArgumentException(\"Message queues can not be null or empty.\");\n        }\n        setSubscriptionType(SubscriptionType.ASSIGN);\n        assignedMessageQueue.updateAssignedMessageQueue(messageQueues);\n        if (serviceState == ServiceState.RUNNING) {\n            updateAssignPullTask(messageQueues);\n        }\n    }\n\n    public synchronized void setSubExpressionForAssign(final String topic, final String subExpression) {\n        if (StringUtils.isBlank(subExpression)) {\n            throw new IllegalArgumentException(\"subExpression can not be null or empty.\");\n        }\n        if (serviceState != ServiceState.CREATE_JUST) {\n            throw new IllegalStateException(\"setAssignTag only can be called before start.\");\n        }\n        setSubscriptionType(SubscriptionType.ASSIGN);\n        topicToSubExpression.put(topic, subExpression);\n    }\n\n    private void maybeAutoCommit() {\n        long now = System.currentTimeMillis();\n        if (now >= nextAutoCommitDeadline) {\n            commitAll();\n            nextAutoCommitDeadline = now + defaultLitePullConsumer.getAutoCommitIntervalMillis();\n        }\n    }\n\n    public synchronized List<MessageExt> poll(long timeout) {\n        try {","sourceCodeStart":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java#L571-L607","documentation":"DefaultLitePullConsumerImpl.setSubExpressionForAssign(topic, subExpression) throws this IllegalArgumentException when subExpression is null, empty, or whitespace (StringUtils.isBlank). The API replaces the default SUB_ALL tag filter for an assigned queue, so a blank expression has no meaning and is rejected.","triggerScenarios":"Calling setSubExpressionForAssign(topic, \"\"), (topic, null), or (topic, \"   \") after using assign().","commonSituations":"Tag expression sourced from user input or config that is blank; passing a trimmed-out placeholder value.","solutions":["Default the expression to \"*\" (SUB_ALL) when blank before calling the method","Validate the expression against the legal TAG syntax if it comes from external input"],"exampleFix":"// before\nconsumer.setSubExpressionForAssign(topic, tagFromConfig);\n\n// after\nString expr = (tagFromConfig == null || tagFromConfig.trim().isEmpty()) ? \"*\" : tagFromConfig;\nconsumer.setSubExpressionForAssign(topic, expr);","handlingStrategy":"validation","validationCode":"String expr = (subExpression == null || subExpression.trim().isEmpty()) ? \"*\" : subExpression;\nconsumer.setSubExpressionForAssign(topic, expr);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat blank tag config as SUB_ALL (\"*\") by convention","Validate tag syntax if the value comes from user input"],"tags":["rocketmq","consumer","assign","tag-filter","validation"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}