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

  1. Inspect e.getCause() (MQBrokerException) and its responseCode to find the real broker error
  2. For offset problems re-sync via fetchMessageQueuesWithQueueOffset or seek to minOffset
  3. For SUBSCRIPTION_GROUP_NOT_EXIST create the group on the broker or enable autoCreateSubscriptionGroup in dev
  4. 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

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


AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14). Data as JSON: /api/errors/d16a914cdfbe6ddd. Report an issue: GitHub.