apache/kafka · error · IllegalArgumentException

topicIdFutures and nameFutures cannot both be null.

Error message

topicIdFutures and nameFutures cannot both be null.

What it means

Thrown by the DeleteTopicsResult protected constructor when both topicIdFutures and nameFutures are null. The result must carry exactly one future map; supplying neither leaves the object in an unusable state with no way to look up results.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsResult.java:40

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

import java.util.Collection;
import java.util.Map;

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

    protected DeleteTopicsResult(Map<Uuid, KafkaFuture<Void>> topicIdFutures, Map<String, KafkaFuture<Void>> 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 DeleteTopicsResult ofTopicIds(Map<Uuid, KafkaFuture<Void>> topicIdFutures) {
        return new DeleteTopicsResult(topicIdFutures, null);
    }

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

    /**
     * Use when {@link Admin#deleteTopics(TopicCollection, DeleteTopicsOptions)} used a TopicIdCollection
     * @return a map from topic IDs to futures which can be used to check the status of
     * individual deletions if the deleteTopics request used topic IDs. Otherwise return null.
     */
    public Map<Uuid, KafkaFuture<Void>> topicIdValues() {

View on GitHub (pinned to 996fb4585a)

Solutions

  1. Use the static factories ofTopicIds / ofTopicNames to guarantee exactly one map is set.
  2. If subclassing, ensure exactly one of the two maps is always provided.
  3. Add constructor assertions in subclasses to fail fast with a clearer message.

Example fix

// before
new DeleteTopicsResult(null, null);

// after
DeleteTopicsResult.ofTopicNames(nameMap);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure exactly one map is non-null
if ((idMap == null) == (nameMap == null)) {
    throw new IllegalArgumentException("Exactly one of topicIdFutures/nameFutures required");
}

Prevention

When it happens

Trigger: Directly instantiating DeleteTopicsResult (or subclass) with null for both the topicIdFutures and nameFutures arguments.

Common situations: Subclass or test code mistakenly passes null/null, or a code path that conditionally builds both maps but ends up selecting neither.

Related errors


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