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
- Check broker logs for the root ConsumeQueueException and affected topic/queueId
- 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)
- If store corruption is indicated, restart the broker to trigger consume-queue recovery, then let consumers re-ack
- 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
- Let pop retry/revive handle un-acked messages instead of hammering ack retries against a failing store
- Monitor broker ConsumeQueueException logs and fix store health promptly
- Avoid deleting topics while pop consumers still hold in-flight messages
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
- Failed to ack message
- Failed to get max offset in queue
- Failed to get max consume offset
- Failed to get max offset in queue or iterate in queue
- Failed to get max offset in queue
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/4a3753b147d2d52e.
Report an issue: GitHub.