apache/rocketmq · error · IllegalArgumentException
Timeout must not be negative
Error message
Timeout must not be negative
What it means
DefaultLitePullConsumerImpl.poll(long timeout) throws IllegalArgumentException("Timeout must not be negative") when timeout < 0. poll() blocks up to timeout milliseconds waiting for a ConsumeRequest from the local cache; a negative timeout is meaningless for that wait and is rejected before any pulling occurs.
Source
Thrown at client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java:610
throw new IllegalStateException("setAssignTag only can be called before start.");
}
setSubscriptionType(SubscriptionType.ASSIGN);
topicToSubExpression.put(topic, subExpression);
}
private void maybeAutoCommit() {
long now = System.currentTimeMillis();
if (now >= nextAutoCommitDeadline) {
commitAll();
nextAutoCommitDeadline = now + defaultLitePullConsumer.getAutoCommitIntervalMillis();
}
}
public synchronized List<MessageExt> poll(long timeout) {
try {
checkServiceState();
if (timeout < 0) {
throw new IllegalArgumentException("Timeout must not be negative");
}
if (defaultLitePullConsumer.isAutoCommit()) {
maybeAutoCommit();
}
long endTime = System.currentTimeMillis() + timeout;
ConsumeRequest consumeRequest = consumeRequestCache.poll(endTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
if (endTime - System.currentTimeMillis() > 0) {
while (consumeRequest != null && consumeRequest.getProcessQueue().isDropped()) {
consumeRequest = consumeRequestCache.poll(endTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
if (endTime - System.currentTimeMillis() <= 0) {
break;
}
}
}
View on GitHub (pinned to 293f588571)
Solutions
- Clamp computed timeouts: Math.max(0, remaining)
- Use a large positive value (or consumerTimeoutMillisWhenSuspend tuning) for long waits instead of -1
- Remember poll(0) is legal and returns immediately
Example fix
// before long remain = deadline - System.currentTimeMillis(); List<MessageExt> msgs = consumer.poll(remain); // after long remain = Math.max(0, deadline - System.currentTimeMillis()); List<MessageExt> msgs = consumer.poll(remain);
Defensive patterns
Strategy: validation
Validate before calling
long safeTimeout = Math.max(0, timeout); List<MessageExt> msgs = consumer.poll(safeTimeout);
Prevention
- Do not reuse Kafka's poll(-1) idiom; RocketMQ requires timeout >= 0
- Always clamp deadline-derived timeouts with Math.max(0, remaining)
When it happens
Trigger: consumer.poll(-1); passing a computed timeout that underflows (e.g. deadline - System.currentTimeMillis() after the deadline passed).
Common situations: Reusing Kafka poll(-1) idiom (infinite block) — RocketMQ does not support it; arithmetic on elapsed time producing negative values.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- consumerGroup can not equal
- Long polling mode, the consumer consumerTimeoutMillisWhenSus
- Topic can not be null or empty.
- Message queues can not be null or empty.
- subExpression can not be null or empty.
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/54d0946837c329c2.
Report an issue: GitHub.