apache/rocketmq · error · RemotingCommandException

Failed to get max offset in queue

Error message

Failed to get max offset in queue

What it means

PeekMessageProcessor (pop-peek, used by proxy lightweight clients) computes remaining messages as maxOffsetInQueue - offset + restNum; a ConsumeQueueException from getMaxOffsetInQueue is wrapped in RemotingCommandException, failing the PEEK_MESSAGE request.

Source

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

            default:
                assert false;
        }
        return response;
    }

    private long peekMsgFromQueue(boolean isRetry, GetMessageResult getMessageResult,
        PeekMessageRequestHeader requestHeader, int queueId, long restNum, int reviveQid, Channel channel,
        long popTime) throws RemotingCommandException {
        String topic = isRetry ?
            KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup(), brokerController.getBrokerConfig().isEnableRetryTopicV2())
            : requestHeader.getTopic();
        GetMessageResult getMessageTmpResult;
        long offset = getPopOffset(topic, requestHeader.getConsumerGroup(), queueId);
        try {
            restNum = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId) - offset + restNum;
        } catch (ConsumeQueueException e) {
            LOG.error("Failed to get max offset in queue. topic={}, queue-id={}", topic, queueId, e);
            throw new RemotingCommandException("Failed to get max offset in queue", e);
        }
        if (getMessageResult.getMessageMapedList().size() >= requestHeader.getMaxMsgNums()) {
            return restNum;
        }
        getMessageTmpResult = this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup(), topic, queueId, offset,
            requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), null);
        // maybe store offset is not correct.
        if (GetMessageStatus.OFFSET_TOO_SMALL.equals(getMessageTmpResult.getStatus()) || GetMessageStatus.OFFSET_OVERFLOW_BADLY.equals(getMessageTmpResult.getStatus())) {
            offset = getMessageTmpResult.getNextBeginOffset();
            getMessageTmpResult = this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup(), topic, queueId, offset,
                requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), null);
        }
        if (getMessageTmpResult != null) {
            if (!getMessageTmpResult.getMessageMapedList().isEmpty() && !isRetry) {
                Attributes attributes = this.brokerController.getBrokerMetricsManager().newAttributesBuilder()
                    .put(LABEL_TOPIC, requestHeader.getTopic())
                    .put(LABEL_CONSUMER_GROUP, requestHeader.getConsumerGroup())
                    .put(LABEL_IS_SYSTEM, TopicValidator.isSystemTopic(requestHeader.getTopic()) || MixAll.isSysConsumerGroup(requestHeader.getConsumerGroup()))

View on GitHub (pinned to 293f588571)

Solutions

  1. Wait for full store initialization on the broker, then retry the peek.
  2. Check the logged topic/queue-id in the LOG.error line to locate the failing queue.
  3. Repair/restore the consume queue store; verify with mqAdmin topicStatus that offsets are queryable.
Defensive patterns

Strategy: retry

Try / catch

catch (RemotingCommandException e) { if (e.getCause() instanceof ConsumeQueueException) { retryPeekWithBackoff(pollIntervalMs); } else throw e; }

Prevention

When it happens

Trigger: Peek request against a topic whose consume queue can't be read — corrupt/missing queue files, store loading, RocksDB read error.

Common situations: Proxy peeking retry/pop-retry topics right after broker restart before store load completes; degraded disk; queue files damaged after crash.

Related errors


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