apache/kafka · error · IllegalArgumentException
The target time for partition {} is {}. The target time cann
Error message
The target time for partition {} is {}. The target time cannot be negative. What it means
Thrown by KafkaConsumer.offsetsForTimes(Map, Duration) when any searched timestamp is negative. The API treats timestamps as non-negative epoch millis (earliest/latest sentinels are handled separately), so a negative value is rejected as a client-side precondition violation before any broker request.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/ClassicKafkaConsumer.java:1024
} finally {
release();
}
}
@Override
public Map<TopicPartition, OffsetAndTimestamp> offsetsForTimes(Map<TopicPartition, Long> timestampsToSearch) {
return offsetsForTimes(timestampsToSearch, Duration.ofMillis(defaultApiTimeoutMs));
}
@Override
public Map<TopicPartition, OffsetAndTimestamp> offsetsForTimes(Map<TopicPartition, Long> timestampsToSearch, Duration timeout) {
acquireAndEnsureOpen();
try {
for (Map.Entry<TopicPartition, Long> entry : timestampsToSearch.entrySet()) {
// we explicitly exclude the earliest and latest offset here so the timestamp in the returned
// OffsetAndTimestamp is always positive.
if (entry.getValue() < 0)
throw new IllegalArgumentException("The target time for partition " + entry.getKey() + " is " +
entry.getValue() + ". The target time cannot be negative.");
}
return offsetFetcher.offsetsForTimes(timestampsToSearch, time.timer(timeout));
} finally {
release();
}
}
@Override
public Map<TopicPartition, Long> beginningOffsets(Collection<TopicPartition> partitions) {
return beginningOffsets(partitions, Duration.ofMillis(defaultApiTimeoutMs));
}
@Override
public Map<TopicPartition, Long> beginningOffsets(Collection<TopicPartition> partitions, Duration timeout) {
acquireAndEnsureOpen();
try {
return offsetFetcher.beginningOffsets(partitions, time.timer(timeout));View on GitHub (pinned to c31c9215e1)
Solutions
- Clamp timestamps to >= 0 before calling: ts = Math.max(0L, ts).
- Use ListOffsets/offsetsForTimes with 0 to mean 'earliest'; do not use negative sentinels.
- Validate time math units are milliseconds and that subtraction cannot go negative.
Example fix
// before long ts = now - lookbackMs; // may be negative consumer.offsetsForTimes(Map.of(tp, ts)); // after long ts = Math.max(0L, now - lookbackMs); consumer.offsetsForTimes(Map.of(tp, ts));
Defensive patterns
Strategy: validation
Validate before calling
// Clamp/normalize timestamps before offsetsForTimes:
Map<TopicPartition, Long> safe = new HashMap<>();
for (var e : timestampsToSearch.entrySet()) {
long t = e.getValue();
if (t < 0) t = 0; // or use ListOffsetsRequest.EARLIEST_TIMESTAMP semantics
safe.put(e.getKey(), t);
}
return consumer.offsetsForTimes(safe, Duration.ofSeconds(30)); Type guard
// A tiny value-object that rejects negatives at construction time:
record NonNegativeTimestamp(long epochMillis) {
NonNegativeTimestamp {
if (epochMillis < 0)
throw new IllegalArgumentException("timestamp must be >= 0");
}
}
// Build the map from NonNegativeTimestamp values; the type makes the bad state unrepresentable. Try / catch
// Recover by clamping the offending entry and retrying once:
try {
return consumer.offsetsForTimes(timestampsToSearch);
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("target time cannot be negative")) throw e;
Map<TopicPartition, Long> clamped = new HashMap<>();
timestampsToSearch.forEach((k, v) -> clamped.put(k, Math.max(0, v)));
return consumer.offsetsForTimes(clamped);
} Prevention
- Never derive search timestamps from System.currentTimeMillis() differences without Math.max(0, ...) — clock skew can produce negatives.
- Reject negative timestamps at the boundary of your own code (CLI parsing, REST handler) so they never propagate to the consumer.
- Use the documented sentinels (OffsetResultStrategy.END_OF_PARTITION / earliest/latest) instead of hand-rolled magic numbers.
When it happens
Trigger: Passing a timestamp computed from System.currentTimeMillis() minus a future or uninitialized value; using -1 as a 'from beginning' sentinel (use offsetsBeginningOffsets instead); clock skew producing negative durations; off-by-one in time math.
Common situations: Replay logic that does (now - lookbackMs) with lookbackMs greater than now due to bad input; passing Optional.orElse(-1L); unit confusion (seconds vs millis) producing negative values; legacy code migrated from a system using -1 as a sentinel.
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
- You can only check the position for partitions assigned to t
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/f19d05254a494a52.json.
Report an issue: GitHub.