apache/kafka · error · IllegalArgumentException

topicIdFutures and nameFutures cannot both be specified.

Error message

topicIdFutures and nameFutures cannot both be specified.

What it means

Thrown by the DescribeTopicsResult protected constructor when both topicIdFutures and nameFutures are non-null. The result holds either a map keyed by topic ID (Uuid) or by topic name, but never both simultaneously — supplying both violates the object's invariant.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsResult.java:41

import org.apache.kafka.common.annotation.InterfaceAudience;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * The result of the {@link KafkaAdminClient#describeTopics(Collection)} call.
 */
@InterfaceAudience.Public
public class DescribeTopicsResult {
    private final Map<Uuid, KafkaFuture<TopicDescription>> topicIdFutures;
    private final Map<String, KafkaFuture<TopicDescription>> nameFutures;

    // VisibleForTesting
    protected DescribeTopicsResult(Map<Uuid, KafkaFuture<TopicDescription>> topicIdFutures, Map<String, KafkaFuture<TopicDescription>> nameFutures) {
        if (topicIdFutures != null && nameFutures != null)
            throw new IllegalArgumentException("topicIdFutures and nameFutures cannot both be specified.");
        if (topicIdFutures == null && nameFutures == null)
            throw new IllegalArgumentException("topicIdFutures and nameFutures cannot both be null.");
        this.topicIdFutures = topicIdFutures;
        this.nameFutures = nameFutures;
    }

    static DescribeTopicsResult ofTopicIds(Map<Uuid, KafkaFuture<TopicDescription>> topicIdFutures) {
        return new DescribeTopicsResult(topicIdFutures, null);
    }

    static DescribeTopicsResult ofTopicNames(Map<String, KafkaFuture<TopicDescription>> nameFutures) {
        return new DescribeTopicsResult(null, nameFutures);
    }

    /**
     * Use when {@link Admin#describeTopics(TopicCollection, DescribeTopicsOptions)} used a TopicIdCollection
     *
     * @return a map from topic IDs to futures which can be used to check the status of

View on GitHub (pinned to 996fb4585a)

Solutions

  1. Use DescribeTopicsResult.ofTopicIds(...) or ofTopicNames(...) instead of the constructor.
  2. If subclassing, pass null for the unused parameter.
  3. Verify test fixtures do not construct the result with both maps.

Example fix

// before
new DescribeTopicsResult(idMap, nameMap);

// after
DescribeTopicsResult.ofTopicIds(idMap);   // or
DescribeTopicsResult.ofTopicNames(nameMap);
Defensive patterns

Strategy: validation

Validate before calling

// Use static factories only
DescribeTopicsResult result = useTopicIds
    ? DescribeTopicsResult.ofTopicIds(idMap)
    : DescribeTopicsResult.ofTopicNames(nameMap);

Prevention

When it happens

Trigger: Directly constructing DescribeTopicsResult (or a subclass) with both the topicIdFutures map and nameFutures map non-null.

Common situations: Test code or a subclass supplies both maps; the static factories ofTopicIds / ofTopicNames are the intended construction paths and avoid this.

Related errors


AI-assisted analysis of apache/kafka@996fb4585a (2026-08-11). Data as JSON: /api/errors/3cfb6f81a51db14f. Report an issue: GitHub.