apache/rocketmq · error · MQClientException
pullCallback is null
Error message
pullCallback is null
What it means
Thrown by pullAsyncImpl when the PullCallback argument is null. Because the async API delivers its result exclusively through the callback, a null callback would make the result unreachable and lose pull outcomes; the client rejects it up front.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java:523
if (null == mq) {
throw new MQClientException("mq is null", null);
}
if (offset < 0) {
throw new MQClientException("offset < 0", null);
}
if (maxNums <= 0) {
throw new MQClientException("maxNums <= 0", null);
}
if (maxSizeInBytes <= 0) {
throw new MQClientException("maxSizeInBytes <= 0", null);
}
if (null == pullCallback) {
throw new MQClientException("pullCallback is null", null);
}
this.subscriptionAutomatically(mq.getTopic());
try {
int sysFlag = PullSysFlag.buildSysFlag(false, block, true, false);
long timeoutMillis = block ? this.defaultMQPullConsumer.getConsumerTimeoutMillisWhenSuspend() : timeout;
boolean isTagType = ExpressionType.isTagType(subscriptionData.getExpressionType());
this.pullAPIWrapper.pullKernelImpl(
mq,
subscriptionData.getSubString(),
subscriptionData.getExpressionType(),
isTagType ? 0L : subscriptionData.getSubVersion(),
offset,
maxNums,
maxSizeInBytes,View on GitHub (pinned to 293f588571)
Solutions
- Always supply a non-null PullCallback; implement both onSuccess and onException
- Use the synchronous pull() if you want a return value instead of a callback
- Initialize callback fields before starting any thread or timer that issues pulls
Example fix
// before
consumer.pullAsync(mq, "*", off, 32, null);
// after
consumer.pullAsync(mq, "*", off, 32, new PullCallback() {
public void onSuccess(PullResult result) { /* handle */ }
public void onException(Throwable e) { /* log + retry */ }
}); Defensive patterns
Strategy: validation
Validate before calling
Objects.requireNonNull(pullCallback, "pullCallback");
Prevention
- Implement both onSuccess and onException in every PullCallback
- Use sync pull() when a return value is wanted
When it happens
Trigger: DefaultMQPullConsumer.pullAsync(mq, expr, offset, maxNums, null); a callback field not yet initialized when the pull loop starts; refactoring inline anonymous PullCallback classes into fields and forgetting the assignment.
Common situations: Constructor-order bugs where pulls are scheduled before the callback is wired; test harnesses passing null intending to use a returned future (which the async API does not provide).
Related errors
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/d49ecb54664f583d.
Report an issue: GitHub.