apache/rocketmq · error · MQClientException
parse subscription error
Error message
parse subscription error
What it means
The catch block of getSubscriptionData wraps any exception from FilterAPI.buildSubscriptionData(topic, subExpression) as MQClientException("parse subscription error", cause). buildSubscriptionData parses a TAG expression; malformed expressions (illegal characters, unbalanced parts after splitting on '||') raise the underlying exception which is rethrown here.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java:210
}
public PullResult pull(MessageQueue mq, MessageSelector messageSelector, long offset, int maxNums, long timeout)
throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
SubscriptionData subscriptionData = getSubscriptionData(mq, messageSelector);
return this.pullSyncImpl(mq, subscriptionData, offset, maxNums, false, timeout);
}
private SubscriptionData getSubscriptionData(MessageQueue mq, String subExpression)
throws MQClientException {
if (null == mq) {
throw new MQClientException("mq is null", null);
}
try {
return FilterAPI.buildSubscriptionData(mq.getTopic(), subExpression);
} catch (Exception e) {
throw new MQClientException("parse subscription error", e);
}
}
private SubscriptionData getSubscriptionData(MessageQueue mq, MessageSelector messageSelector)
throws MQClientException {
if (null == mq) {
throw new MQClientException("mq is null", null);
}
try {
return FilterAPI.build(mq.getTopic(),
messageSelector.getExpression(), messageSelector.getExpressionType());
} catch (Exception e) {
throw new MQClientException("parse subscription error", e);
}
}
View on GitHub (pinned to 293f588571)
Solutions
- Validate/normalize the expression: non-empty operands around each '||', no whitespace inside a tag unless intended
- Call e.getCause() to see the precise parse failure from FilterAPI
- Build expressions from a validated tag vocabulary rather than raw concatenation
Example fix
// before
String expr = String.join("||", tags); // may end with '||' if a tag is empty
consumer.pull(mq, expr, 0, 32, 3000);
// after
String expr = tags.stream().filter(t -> t != null && !t.trim().isEmpty()).collect(Collectors.joining("||"));
consumer.pull(mq, expr, 0, 32, 3000); Defensive patterns
Strategy: validation
Validate before calling
String expr = Arrays.stream(subExpr.split("\\|\\|"))
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.joining("||"));
if (expr.isEmpty()) expr = "*"; Try / catch
try {
consumer.pull(mq, expr, offset, maxNums, timeout);
} catch (MQClientException e) {
if (e.getCause() != null) {
// parse failure — fix expression, never retry unchanged
}
} Prevention
- Build tag expressions from validated, non-empty operands
- Cover expression construction with unit tests that run FilterAPI.buildSubscriptionData
When it happens
Trigger: consumer.pull(mq, "TAG A ||", ...) with a trailing separator; subExpression containing characters illegal in a tag; expression built by string concatenation with a stray '||'.
Common situations: User-supplied tag filters; dynamically assembled OR-expressions where an operand is empty.
Related errors
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/aff968213013e421.
Report an issue: GitHub.