apache/rocketmq · error · MQClientException
offset < 0
Error message
offset < 0
What it means
Thrown by pullSyncImpl when the requested starting offset is negative. Pull offsets are logical positions into a commit log queue; a negative offset is meaningless and is rejected before any network call is made.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java:239
try {
return FilterAPI.build(mq.getTopic(),
messageSelector.getExpression(), messageSelector.getExpressionType());
} catch (Exception e) {
throw new MQClientException("parse subscription error", e);
}
}
private PullResult pullSyncImpl(MessageQueue mq, SubscriptionData subscriptionData, long offset, int maxNums, boolean block,
long timeout)
throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
this.isRunning();
if (null == mq) {
throw new MQClientException("mq is null", null);
}
if (offset < 0) {
throw new MQClientException("offset < 0", null);
}
if (maxNums <= 0) {
throw new MQClientException("maxNums <= 0", null);
}
this.subscriptionAutomatically(mq.getTopic());
int sysFlag = PullSysFlag.buildSysFlag(false, block, true, false);
long timeoutMillis = block ? this.defaultMQPullConsumer.getConsumerTimeoutMillisWhenSuspend() : timeout;
boolean isTagType = ExpressionType.isTagType(subscriptionData.getExpressionType());
PullResult pullResult = this.pullAPIWrapper.pullKernelImpl(
mq,
subscriptionData.getSubString(),
subscriptionData.getExpressionType(),
isTagType ? 0L : subscriptionData.getSubVersion(),View on GitHub (pinned to 293f588571)
Solutions
- Use consumer.fetchMessageQueuesWithQueueOffset(...) or the OffsetStore to obtain a valid starting offset
- Clamp computed offsets: long safe = Math.max(0, offset)
- For 'start at earliest/latest' semantics query minOffset/maxOffset from the broker instead of inventing sentinels
Example fix
// before long offset = currentOffset - backTrack; // may go negative consumer.pull(mq, "*", offset, 32); // after long offset = Math.max(mqMinOffset, currentOffset - backTrack); consumer.pull(mq, "*", offset, 32);
Defensive patterns
Strategy: validation
Validate before calling
if (offset < 0) throw new IllegalArgumentException("offset must be >= 0, got " + offset); Prevention
- Never use -1 as a sentinel offset
- Clamp arithmetic on offsets to minOffset
When it happens
Trigger: DefaultMQPullConsumer.pull(mq, expr, offset, maxNums) with offset < 0; computing offset as 'minOffset - diff' or 'offset - pulled' that underflows; passing -1 as a sentinel 'start from beginning' value instead of fetchMessageQueuesWithQueueOffset.
Common situations: Developers using -1 to mean 'latest' (the correct sentinel is obtained from fetchMessageQueueOffset / maxOffset); arithmetic that subtracts more than the current offset; offsets loaded from a corrupt external store.
Related errors
- maxNums <= 0
- maxSizeInBytes <= 0
- Failed to get max offset
- Failed to query initial offset
- Seek offset illegal, seek offset =
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/0e525822eadc3532.
Report an issue: GitHub.