apache/kafka · error · java.lang.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

IllegalArgumentException from offsetsForTimes when any value in the timestampsToSearch map is negative. The broker's ListOffsets request interprets special non-negative sentinels (earliest=-2, latest=-1 internally), but the public consumer API exposes those via beginningOffsets/endOffsets; user-supplied timestamps must be wall-clock milliseconds >= 0. The message names the offending partition and value to aid diagnosis.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/AsyncKafkaConsumer.java:1413

    }

    @Override
    public Map<TopicPartition, OffsetAndTimestamp> offsetsForTimes(Map<TopicPartition, Long> timestampsToSearch) {
        return offsetsForTimes(timestampsToSearch, defaultApiTimeoutMs);
    }

    @Override
    public Map<TopicPartition, OffsetAndTimestamp> offsetsForTimes(Map<TopicPartition, Long> timestampsToSearch, Duration timeout) {
        acquireAndEnsureOpen();
        try {
            // Keeping same argument validation error thrown by the current consumer implementation
            // to avoid API level changes.
            requireNonNull(timestampsToSearch, "Timestamps to search cannot be null");
            for (Map.Entry<TopicPartition, Long> entry : timestampsToSearch.entrySet()) {
                // 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.");
            }

            if (timestampsToSearch.isEmpty()) {
                return Collections.emptyMap();
            }
            ListOffsetsEvent listOffsetsEvent = new ListOffsetsEvent(
                    timestampsToSearch,
                    calculateDeadlineMs(time, timeout),
                    true);

            // If timeout is set to zero return empty immediately; otherwise try to get the results
            // and throw timeout exception if it cannot complete in time.
            if (timeout.toMillis() == 0L) {
                applicationEventHandler.add(listOffsetsEvent);
                return listOffsetsEvent.emptyResults();
            }

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Replace negative sentinel values with real epoch-millis timestamps or use beginningOffsets()/endOffsets() for earliest/latest semantics.
  2. Sanitize the map before calling: timestampsToSearch.values().removeIf(v -> v < 0).
  3. Validate the source of timestamps; default missing/unknown entries to System.currentTimeMillis() or 0 (start-of-time).

Example fix

// before
Map<TopicPartition, Long> q = Map.of(tp, -1L);
consumer.offsetsForTimes(q); // throws

// after
Map<TopicPartition, Long> q = Map.of(tp, System.currentTimeMillis() - 3600_000L);
consumer.offsetsForTimes(q);
Defensive patterns

Strategy: validation

Validate before calling

Map<TopicPartition, Long> safe = new HashMap<>();
timestampsToSearch.forEach((tp, ts) -> {
    if (ts == null || ts < 0L) {
        throw new IllegalArgumentException("timestamp for " + tp + " must be >= 0; use -1 semantics via ListOffsetsRequest only inside the client");
    }
    safe.put(tp, ts);
});
consumer.offsetsForTimes(safe, timeout);

Type guard

boolean allTimestampsNonNegative(Map<TopicPartition, Long> ts) {
    return ts != null && ts.values().stream().allMatch(v -> v != null && v >= 0L);
}

Prevention

When it happens

Trigger: Calling consumer.offsetsForTimes(Map<TopicPartition, Long>) where any Long value is < 0, including passing ListOffsetsRequest.EARLIEST_TIMESTAMP (-2) / LATEST_TIMESTAMP (-1) constants (which are internal sentinels), or using -1 as a 'not found' placeholder, or computing timestamp = someDate.getTime() from a null/epoch Date that yields 0 or negative.

Common situations: Copy-paste from internal broker code that uses LATEST_TIMESTAMP/EARLIEST_TIMESTAMP constants; deriving search timestamps from event headers that default to -1; arithmetic like System.currentTimeMillis() - retentionMs that underflows due to misconfigured retention; clock-skew scenarios producing negative deltas.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/ea42a05e9f132753.json. Report an issue: GitHub.