apache/rocketmq · error · RemotingCommandException

Failed to get max offset

Error message

Failed to get max offset

What it means

AckMessageProcessor's single-ack path (used for pop consumers) validates the acked offset against [minOffset, maxOffset]; the max offset comes from messageStore.getMaxOffsetInQueue(), whose checked ConsumeQueueException is wrapped as RemotingCommandException('Failed to get max offset'). The ack request fails at the store layer before offset-legality checks or commit logic run.

Source

Thrown at broker/src/main/java/org/apache/rocketmq/broker/processor/AckMessageProcessor.java:155

                String errorInfo = String.format("queueId[%d] is illegal, topic:[%s] topicConfig.readQueueNums:[%d] consumer:[%s]",
                    requestHeader.getQueueId(), requestHeader.getTopic(), topicConfig.getReadQueueNums(), channel.remoteAddress());
                POP_LOGGER.warn(errorInfo);
                response.setCode(ResponseCode.MESSAGE_ILLEGAL);
                response.setRemark(errorInfo);
                return response;
            }

            RemotingCommand ackLiteResponse = ackLite(requestHeader, null, response, channel);
            if (ackLiteResponse != null) {
                return ackLiteResponse;
            }

            long minOffset = this.brokerController.getMessageStore().getMinOffsetInQueue(requestHeader.getTopic(), requestHeader.getQueueId());
            long maxOffset;
            try {
                maxOffset = this.brokerController.getMessageStore().getMaxOffsetInQueue(requestHeader.getTopic(), requestHeader.getQueueId());
            } catch (ConsumeQueueException e) {
                throw new RemotingCommandException("Failed to get max offset", e);
            }
            if (requestHeader.getOffset() < minOffset || requestHeader.getOffset() > maxOffset) {
                String errorInfo = String.format("offset is illegal, key:%s@%d, commit:%d, store:%d~%d",
                    requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getOffset(), minOffset, maxOffset);
                POP_LOGGER.warn(errorInfo);
                response.setCode(ResponseCode.NO_MESSAGE);
                response.setRemark(errorInfo);
                return response;
            }
            if (brokerController.getBrokerConfig().isPopConsumerKVServiceEnable()) {
                appendAckNew(requestHeader, null, response, channel, null);
            } else {
                appendAck(requestHeader, null, response, channel, null);
            }
        } else if (request.getCode() == RequestCode.BATCH_ACK_MESSAGE) {
            if (request.getBody() != null) {
                reqBody = BatchAckMessageRequestBody.decode(request.getBody(), BatchAckMessageRequestBody.class);
            }

View on GitHub (pinned to 293f588571)

Solutions

  1. Check broker logs for the root ConsumeQueueException and affected topic/queueId
  2. Confirm the topic and queue still exist on this broker (deleted queues cannot be acked; pop messages from a revived queue will retry/expire via the revive mechanism)
  3. If store corruption is indicated, restart the broker to trigger consume-queue recovery, then let consumers re-ack
  4. Retry acking after the broker is healthy; pop retries will redeliver un-acked messages
Defensive patterns

Strategy: retry

Try / catch

try {
    popConsumer.ack(msg);
} catch (Exception e) {
    Throwable real = ExceptionUtils.getRealException(e);
    if (real instanceof RemotingCommandException) {
        // transient store failure: wait for broker recovery; pop revive will redeliver
    }
}

Prevention

When it happens

Trigger: A pop consumer sending an AckMessage request for a topic/queue whose consume queue read throws — queue deleted (topic deleted concurrently), consume queue files corrupt, or store shutting down.

Common situations: Acks arriving right as a topic is deleted or migrated; store recovery/replay in progress; disk corruption on the consumeq directory.

Related errors


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