apache/kafka · error · IllegalArgumentException

List Offsets for partition "{partition}" was not attempted

Error message

List Offsets for partition "{partition}" was not attempted

What it means

Thrown by ListOffsetsResult.partitionResult(partition) when the given TopicPartition was not included in the original listOffsets request. The Admin client stores a future only for each requested partition; querying an unrequested partition is a client-side programming error.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/admin/ListOffsetsResult.java:47

/**
 * The result of the {@link AdminClient#listOffsets(Map)} call.
 */
@InterfaceAudience.Public
public class ListOffsetsResult {

    private final Map<TopicPartition, KafkaFuture<ListOffsetsResultInfo>> futures;

    public ListOffsetsResult(Map<TopicPartition, KafkaFuture<ListOffsetsResultInfo>> futures) {
        this.futures = futures;
    }

    /**
    * Return a future which can be used to check the result for a given partition.
    */
    public KafkaFuture<ListOffsetsResultInfo> partitionResult(final TopicPartition partition) {
        KafkaFuture<ListOffsetsResultInfo> future = futures.get(partition);
        if (future == null) {
            throw new IllegalArgumentException(
                    "List Offsets for partition \"" + partition + "\" was not attempted");
        }
        return future;
    }

    /**
     * Return a future which succeeds only if offsets for all specified partitions have been successfully
     * retrieved.
     */
    public KafkaFuture<Map<TopicPartition, ListOffsetsResultInfo>> all() {
        return KafkaFuture.allOf(futures.values().toArray(new KafkaFuture<?>[0]))
                .thenApply(v -> {
                    Map<TopicPartition, ListOffsetsResultInfo> offsets = new HashMap<>(futures.size());
                    for (Map.Entry<TopicPartition, KafkaFuture<ListOffsetsResultInfo>> entry : futures.entrySet()) {
                        try {
                            offsets.put(entry.getKey(), entry.getValue().get());
                        } catch (InterruptedException | ExecutionException e) {
                            // This should be unreachable, because allOf ensured that all the futures completed successfully.

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Pass the exact same TopicPartition objects used in the listOffsets request when calling partitionResult
  2. Build the request map once and iterate its keySet() when accessing per-partition results
  3. Prefer the all() accessor when you need every requested partition's result

Example fix

// before
Map<TopicPartition, OffsetSpec> req = new HashMap<>();
req.put(new TopicPartition("t", 0), OffsetSpec.latest());
ListOffsetsResult r = admin.listOffsets(req);
r.partitionResult(new TopicPartition("t", 1)); // throws

// after
for (TopicPartition tp : req.keySet()) {
    r.partitionResult(tp).get();
}
Defensive patterns

Strategy: validation

Validate before calling

// Keep the set of TopicPartitions handed to listOffsets and check membership.
Set<TopicPartition> requested = new HashSet<>(offsetSpecs.keySet());
TopicPartition tp = ...;
if (!requested.contains(tp)) {
    // partition was not in the listOffsets request; skip or fix caller
    return;
}
ListOffsetsResult result = admin.listOffsets(offsetSpecs);
result.partitionResult(tp).get();

Type guard

static Optional<TopicPartition> requestedPartition(Set<TopicPartition> requested, TopicPartition tp) {
    return tp != null && requested.contains(tp) ? Optional.of(tp) : Optional.empty();
}

Try / catch

try {
    result.partitionResult(tp).get();
} catch (IllegalArgumentException e) {
    // tp was not part of the listOffsets request map;
    // reconcile the partition set the caller queries against the one it sent.
    log.warn("Partition {} was not in the listOffsets request", tp);
}

Prevention

When it happens

Trigger: Calling result.partitionResult(tp) where tp was not a key in the Map<TopicPartition, OffsetSpec> passed to Admin.listOffsets. Common when the set of partitions iterated at result time differs from (or is a superset of) the set passed at request time.

Common situations: Listing offsets for partitions of a topic, then querying a partition that was added or renumbered between request and result handling; passing partitions discovered from metadata that includes partitions filtered out of the request; off-by-one partition index loops.

Related errors


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