apache/kafka · error · java.lang.IllegalArgumentException

Topic collection to subscribe to cannot be null

Error message

Topic collection to subscribe to cannot be null

What it means

Thrown by AsyncKafkaConsumer.subscribeInternal as an IllegalArgumentException when the topics argument is null. The async consumer refuses a null collection before it can enter the background event pipeline, because there is no meaningful subscription event to enqueue. It is a fast-fail guard that mirrors the classic consumer's contract so caller bugs surface at the API boundary rather than as NPEs on the network thread.

Source

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

            release();
        }
    }

    private void throwIfSubscriptionPatternIsInvalid(SubscriptionPattern subscriptionPattern) {
        if (subscriptionPattern == null) {
            throw new IllegalArgumentException("Topic pattern to subscribe to cannot be null");
        }
        if (subscriptionPattern.pattern().isEmpty()) {
            throw new IllegalArgumentException("Topic pattern to subscribe to cannot be empty");
        }
    }

    private void subscribeInternal(Collection<String> topics, Optional<ConsumerRebalanceListener> listener) {
        acquireAndEnsureOpen();
        try {
            throwIfGroupIdNotDefined();
            if (topics == null)
                throw new IllegalArgumentException("Topic collection to subscribe to cannot be null");
            if (topics.isEmpty()) {
                // treat subscribing to empty topic list as the same as unsubscribing
                unsubscribe();
            } else {
                for (String topic : topics) {
                    if (isBlank(topic))
                        throw new IllegalArgumentException("Topic collection to subscribe to cannot contain null or empty topic");
                }

                // Clear the buffered data which are not a part of newly assigned topics
                final Set<TopicPartition> currentTopicPartitions = new HashSet<>();

                for (TopicPartition tp : subscriptions.assignedPartitions()) {
                    if (topics.contains(tp.topic()))
                        currentTopicPartitions.add(tp);
                }

                fetchBuffer.retainAll(currentTopicPartitions);

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Initialize the topic collection before calling subscribe, e.g. pass Collections.singletonList("my-topic") or an explicitly built Set<String>.
  2. If the topic list is genuinely optional, guard the call site: if (topics != null && !topics.isEmpty()) consumer.subscribe(topics); else consumer.unsubscribe();
  3. Audit framework adapters (Spring Kafka, Micronaut Kafka) that bridge into KafkaConsumer to ensure they never forward a null collection.
  4. Add a unit test asserting subscribe(null) throws IllegalArgumentException so regressions are caught at the boundary.

Example fix

// before
consumer.subscribe((Collection<String>) null);

// after
consumer.subscribe(Collections.singletonList("orders"));
Defensive patterns

Strategy: validation

Validate before calling

// Before consumer.subscribe(topics):
if (topics == null) {
    throw new IllegalArgumentException("topics must not be null");
}
// or normalize: Collection<String> safe = (topics == null) ? List.of() : topics;

Type guard

// Java has no null-narrowing; guard at call site.
// Optional<Collection<String>> nonNullTopics = Optional.ofNullable(topics);
// nonNullTopics.ifPresent(consumer::subscribe);

Try / catch

// Safety net only; prefer pre-validation.
try {
    consumer.subscribe(topics);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("cannot be null")) {
        log.warn("subscribe called with null topics; skipping");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling consumer.subscribe((Collection<String>) null) or subscribe((Collection<String>) null, listener) on an AsyncKafkaConsumer instance; also triggered indirectly by frameworks that forward a nullable topic list (e.g. Spring Kafka's ContainerProperties when topic list is unset) into the new KIP-848 async consumer.

Common situations: Migrating to the async consumer (group.protocol=consumer) where a previously-tolerated null is now guarded; reflection/dependency-injection wiring that has not yet resolved the topic list at construction time; copy-paste from assign() code paths where null is handled differently.

Related errors


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