apache/kafka · error · IllegalArgumentException
The timeout cannot be negative.
Error message
The timeout cannot be negative.
What it means
Thrown by KafkaConsumer.close(CloseOptions) when the configured close timeout is negative. The check is a simple precondition on option.timeout() (or the default DEFAULT_CLOSE_TIMEOUT_MS), since a negative duration is not a meaningful wait. It occurs before any resource cleanup, so no leak is caused.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/ClassicKafkaConsumer.java:1122
close(CloseOptions.timeout(Duration.ofMillis(DEFAULT_CLOSE_TIMEOUT_MS)));
}
@Deprecated
@Override
public void close(Duration timeout) {
close(CloseOptions.timeout(timeout));
}
@Override
public void wakeup() {
this.client.wakeup();
}
@Override
public void close(CloseOptions option) {
Duration timeout = option.timeout().orElseGet(() -> Duration.ofMillis(DEFAULT_CLOSE_TIMEOUT_MS));
if (timeout.toMillis() < 0)
throw new IllegalArgumentException("The timeout cannot be negative.");
acquire();
try {
if (!closed) {
// need to close before setting the flag since the close function
// itself may trigger rebalance callback that needs the consumer to be open still
close(timeout, option.groupMembershipOperation(), false);
}
} finally {
closed = true;
release();
}
}
private Timer createTimerForRequest(final Duration timeout) {
// this.time could be null if an exception occurs in constructor prior to setting the this.time field
final Time localTime = (time == null) ? Time.SYSTEM : time;
return localTime.timer(Math.min(timeout.toMillis(), requestTimeoutMs));
}View on GitHub (pinned to c31c9215e1)
Solutions
- Clamp the close timeout to a non-negative value: Duration.ofMillis(Math.max(0, ms)).
- Fix the source of the negative number (config typo or bad time math).
- Use the no-arg close() or CloseOptions.timeout(Duration.ofSeconds(30)) defaults instead of computing your own.
Example fix
// before consumer.close(new CloseOptions().timeout(Duration.ofMillis(timeoutMs))); // timeoutMs < 0 // after long safe = Math.max(0L, timeoutMs); consumer.close(new CloseOptions().timeout(Duration.ofMillis(safe)));
Defensive patterns
Strategy: validation
Validate before calling
// Validate the timeout you hand to close(CloseOptions) / close(Duration):
Duration closeTimeout = option.timeout().orElse(Duration.ofMillis(DEFAULT_CLOSE_TIMEOUT_MS));
if (closeTimeout == null || closeTimeout.isNegative()) {
closeTimeout = Duration.ofMillis(DEFAULT_CLOSE_TIMEOUT_MS);
}
consumer.close(CloseOptions.timeout(closeTimeout)); Type guard
// A guard helper that returns a guaranteed-non-negative Duration:
static Duration nonNegative(Duration d, Duration fallback) {
return (d == null || d.isNegative()) ? fallback : d;
}
// Usage: consumer.close(nonNegative(configured, Duration.ofSeconds(30))); Try / catch
// Treat a negative-timeout close() as a programming error; fall back to the default and retry once:
try {
consumer.close(opts);
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("timeout cannot be negative")) throw e;
consumer.close(); // default timeout
} Prevention
- Compute close timeouts from absolute configs (Duration.ofMillis(X)) rather than arithmetic on (deadline - now), which can go negative past the deadline.
- Clamp every externally-supplied duration through one helper before it touches any Kafka client method.
- Unit-test your config layer with a deliberately negative value to prove it gets normalized.
When it happens
Trigger: Constructing CloseOptions.timeout(Duration.ofMillis(-1)); passing a computed Duration that subtracted past zero; serializing a timeout from config that parsed negative; reusing a Duration object that was decremented in a loop.
Common situations: Misconfiguring request.timeout.ms or close timeout to a negative number; arithmetic on durations without a floor; copying examples that used a now-removed overload; properties files with negative integers due to typos.
Related errors
- Topic partitions to assign to cannot have null or empty topi
- RebalanceListener cannot be null
- Topic pattern to subscribe to cannot be null
- Topic pattern to subscribe to cannot be empty
- Telemetry is not enabled. Set config `{}` to `true`.
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/11157362cd01eab1.json.
Report an issue: GitHub.