apache/rocketmq · error · MQClientException
pullAsync unknown exception
Error message
pullAsync unknown exception
What it means
Thrown by pullAsyncImpl when the underlying pullKernelImpl call raises an MQBrokerException. Because the async protocol has no callback to deliver a broker-side failure, the exception is wrapped in an MQClientException with the generic label 'pullAsync unknown exception'; the original broker error (response code and remark) is preserved as the cause.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java:562
this.defaultMQPullConsumer.getBrokerSuspendMaxTimeMillis(),
timeoutMillis,
CommunicationMode.ASYNC,
new PullCallback() {
@Override
public void onSuccess(PullResult pullResult) {
PullResult userPullResult = DefaultMQPullConsumerImpl.this.pullAPIWrapper.processPullResult(mq, pullResult, subscriptionData);
resetTopic(userPullResult.getMsgFoundList());
pullCallback.onSuccess(userPullResult);
}
@Override
public void onException(Throwable e) {
pullCallback.onException(e);
}
});
} catch (MQBrokerException e) {
throw new MQClientException("pullAsync unknown exception", e);
}
}
private void pullAsyncImpl(
final MessageQueue mq,
final SubscriptionData subscriptionData,
final long offset,
final int maxNums,
final PullCallback pullCallback,
final boolean block,
final long timeout) throws MQClientException, RemotingException, InterruptedException {
pullAsyncImpl(
mq,
subscriptionData,
offset,
maxNums,
Integer.MAX_VALUE,
pullCallback,View on GitHub (pinned to 293f588571)
Solutions
- Inspect e.getCause() (MQBrokerException) and its responseCode to find the real broker error
- For offset problems re-sync via fetchMessageQueuesWithQueueOffset or seek to minOffset
- For SUBSCRIPTION_GROUP_NOT_EXIST create the group on the broker or enable autoCreateSubscriptionGroup in dev
- For filter issues ensure the same selector was used previously so the broker compiled the filter, or retry to let it upload
Example fix
// before
catch (MQClientException e) {
log.error("pull failed", e); // opaque generic message
}
// after
catch (MQClientException e) {
Throwable cause = e.getCause();
if (cause instanceof MQBrokerException) {
MQBrokerException be = (MQBrokerException) cause;
if (be.getResponseCode() == ResponseCode.OFFSET_ILLEGAL) {
long off = consumer.minOffset(mq);
consumer.getOffsetStore().updateOffset(mq, off, false);
return; // next pull uses corrected offset
}
}
throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
catch (MQClientException e) {
if (e.getCause() instanceof MQBrokerException) {
MQBrokerException be = (MQBrokerException) e.getCause();
switch (be.getResponseCode()) {
case ResponseCode.OFFSET_ILLEGAL: /* resync offset */ break;
case ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST: /* create group */ break;
default: throw e;
}
} else throw e;
} Prevention
- Always inspect the MQBrokerException cause for the real response code
- Validate offsets against min/maxOffset before pulling
- Ensure consumer groups and filters exist on the broker before async pulls
When it happens
Trigger: Broker returns a non-zero ResponseCode during an async pull: OFFSET_ILLEGAL / OFFSET_OVERFLOW_BADLY when the offset is out of the queue's valid range, SUBSCRIPTION_GROUP_NOT_EXIST, FILTER_DATA_NOT_EXIST, or BROKER suspended; the wrapping happens in the catch (MQBrokerException e) around pullAPIWrapper.pullKernelImpl.
Common situations: Pulling with an offset beyond maxOffset (e.g. after messages expired and the queue was truncated); consumer group not created on the broker (autoCreateSubscriptionGroup disabled); SQL92 filter class data not registered on the broker; broker overloaded returning SYSTEM_BUSY.
Related errors
- maxSizeInBytes <= 0
- pullCallback is null
- offset < 0
- maxNums <= 0
- Broker[{destBrokerName}] master node does not exist
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/d16a914cdfbe6ddd.
Report an issue: GitHub.