apache/rocketmq · error · RemotingCommandException

Failed to get max offset in queue

Error message

Failed to get max offset in queue

What it means

AckMessageProcessor's batch-ack handling (ackLite/batch path) resolves the queue's max offset via getMaxOffsetInQueue(topic, qId) to sanity-check each acked offset; a ConsumeQueueException from that lookup is wrapped in RemotingCommandException('Failed to get max offset in queue'). The whole batch ack aborts — none of its offsets are committed.

Source

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

            ackMsg = new AckMsg();
            ackCount = 1;
        } else {
            // batch ack
            consumeGroup = batchAck.getConsumerGroup();
            topic = ExtraInfoUtil.getRealTopic(batchAck.getTopic(), batchAck.getConsumerGroup(), batchAck.getRetry());
            qId = batchAck.getQueueId();
            rqId = batchAck.getReviveQueueId();
            startOffset = batchAck.getStartOffset();
            ackOffset = -1;
            popTime = batchAck.getPopTime();
            invisibleTime = batchAck.getInvisibleTime();

            long minOffset = this.brokerController.getMessageStore().getMinOffsetInQueue(topic, qId);
            long maxOffset;
            try {
                maxOffset = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, qId);
            } catch (ConsumeQueueException e) {
                throw new RemotingCommandException("Failed to get max offset in queue", e);
            }
            if (minOffset == -1 || maxOffset == -1) {
                POP_LOGGER.error("Illegal topic or queue found when batch ack {}", batchAck);
                return;
            }

            BatchAckMsg batchAckMsg = new BatchAckMsg();
            BitSet bitSet = batchAck.getBitSet();
            for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
                if (i == Integer.MAX_VALUE) {
                    break;
                }
                long offset = startOffset + i;
                if (offset < minOffset || offset > maxOffset) {
                    continue;
                }
                if (rqId == KeyBuilder.POP_ORDER_REVIVE_QUEUE) {
                    ackOrderly(topic, consumeGroup, qId, offset, popTime, invisibleTime, channel, response);

View on GitHub (pinned to 293f588571)

Solutions

  1. Locate the underlying ConsumeQueueException cause in broker logs for the exact topic/queue
  2. Ensure the topic/queue still exists before clients batch-ack; removed queues should be skipped by clients
  3. Recover/rebuild consume queues via broker restart if files are corrupt
  4. After recovery, rely on pop retry/revive to redeliver the un-acked batch rather than resubmitting stale acks
Defensive patterns

Strategy: retry

Try / catch

try {
    popConsumer.ack(batch);
} catch (Exception e) {
    Throwable real = ExceptionUtils.getRealException(e);
    if (real instanceof RemotingCommandException) { /* whole batch aborted; rely on pop redelivery after store recovery */ }
}

Prevention

When it happens

Trigger: BatchAckMessage requests from pop consumers when the target topic/queue's consume queue read fails (queue removed mid-flight, corrupt consumeq files, store closing).

Common situations: Pop consumers with batch acking enabled acking against a topic being deleted or whose queue was trimmed; store in recovery; same corruption scenarios as the single-ack path but affecting the entire batch.

Related errors


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