apache/rocketmq · error · IllegalArgumentException
subExpression can not be null or empty.
Error message
subExpression can not be null or empty.
What it means
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.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java:589
this.rebalanceImpl.getSubscriptionInner().remove(topic);
removePullTaskCallback(topic);
assignedMessageQueue.removeAssignedMessageQueue(topic);
}
public synchronized void assign(Collection<MessageQueue> messageQueues) {
if (messageQueues == null || messageQueues.isEmpty()) {
throw new IllegalArgumentException("Message queues can not be null or empty.");
}
setSubscriptionType(SubscriptionType.ASSIGN);
assignedMessageQueue.updateAssignedMessageQueue(messageQueues);
if (serviceState == ServiceState.RUNNING) {
updateAssignPullTask(messageQueues);
}
}
public synchronized void setSubExpressionForAssign(final String topic, final String subExpression) {
if (StringUtils.isBlank(subExpression)) {
throw new IllegalArgumentException("subExpression can not be null or empty.");
}
if (serviceState != ServiceState.CREATE_JUST) {
throw new IllegalStateException("setAssignTag only can be called before start.");
}
setSubscriptionType(SubscriptionType.ASSIGN);
topicToSubExpression.put(topic, subExpression);
}
private void maybeAutoCommit() {
long now = System.currentTimeMillis();
if (now >= nextAutoCommitDeadline) {
commitAll();
nextAutoCommitDeadline = now + defaultLitePullConsumer.getAutoCommitIntervalMillis();
}
}
public synchronized List<MessageExt> poll(long timeout) {
try {View on GitHub (pinned to 293f588571)
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
Example fix
// before consumer.setSubExpressionForAssign(topic, tagFromConfig); // after String expr = (tagFromConfig == null || tagFromConfig.trim().isEmpty()) ? "*" : tagFromConfig; consumer.setSubExpressionForAssign(topic, expr);
Defensive patterns
Strategy: validation
Validate before calling
String expr = (subExpression == null || subExpression.trim().isEmpty()) ? "*" : subExpression; consumer.setSubExpressionForAssign(topic, expr);
Prevention
- Treat blank tag config as SUB_ALL ("*") by convention
- Validate tag syntax if the value comes from user input
When it happens
Trigger: Calling setSubExpressionForAssign(topic, ""), (topic, null), or (topic, " ") after using assign().
Common situations: Tag expression sourced from user input or config that is blank; passing a trimmed-out placeholder value.
Related errors
- Message queues can not be null or empty.
- The message queue is not in assigned list, message queue:
- consumerGroup can not equal
- Topic can not be null or empty.
- Timeout must not be negative
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/f30fcf56fffecc61.
Report an issue: GitHub.