apache/kafka · error · java.lang.IllegalArgumentException

Topic partitions to assign to cannot have null or empty topi

Error message

Topic partitions to assign to cannot have null or empty topic

What it means

Thrown by KafkaConsumer.assign(Collection<TopicPartition>) when the passed collection is non-null and non-empty but contains a TopicPartition whose topic name is null, empty, or whitespace-only. The client validates every TopicPartition before publishing an AssignmentChangeEvent so the background network thread never has to deal with malformed partition metadata. It is a programmer error, not a transient runtime condition.

Source

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

    }

    @Override
    public void assign(Collection<TopicPartition> partitions) {
        acquireAndEnsureOpen();
        try {
            if (partitions == null) {
                throw new IllegalArgumentException("Topic partitions collection to assign to cannot be null");
            }

            if (partitions.isEmpty()) {
                unsubscribe();
                return;
            }

            for (TopicPartition tp : partitions) {
                String topic = (tp != null) ? tp.topic() : null;
                if (isBlank(topic))
                    throw new IllegalArgumentException("Topic partitions to assign to cannot have 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 (partitions.contains(tp))
                    currentTopicPartitions.add(tp);
            }

            fetchBuffer.retainAll(currentTopicPartitions);

            // assignment change event will trigger autocommit if it is configured and the group id is specified. This is
            // to make sure offsets of topic partitions the consumer is unsubscribing from are committed since there will
            // be no following rebalance.
            //
            // See the ApplicationEventProcessor.process() method that handles this event for more detail.
            applicationEventHandler.addAndGet(new AssignmentChangeEvent(

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Validate each topic name before building the TopicPartition: filter out null/blank strings or fail fast with a clear upstream error.
  2. Log the offending TopicPartition (toString) in a wrapping try/catch to identify which element is malformed.
  3. If the topic list comes from configuration, ensure the property is non-empty and trim whitespace before use.
  4. Add a unit test that asserts assign() receives only well-formed TopicPartition objects.

Example fix

// before
List<TopicPartition> parts = topics.stream()
    .map(t -> new TopicPartition(t, 0))
    .collect(Collectors.toList());
consumer.assign(parts);

// after
List<TopicPartition> parts = topics.stream()
    .filter(t -> t != null && !t.trim().isEmpty())
    .map(t -> new TopicPartition(t.trim(), 0))
    .collect(Collectors.toList());
if (parts.isEmpty()) throw new IllegalArgumentException("no valid topics");
consumer.assign(parts);
Defensive patterns

Strategy: validation

Validate before calling

// Before consumer.assign(partitions):
if (partitions == null) throw new IllegalArgumentException("partitions is null");
for (TopicPartition tp : partitions) {
    if (tp == null || tp.topic() == null || tp.topic().trim().isEmpty()) {
        throw new IllegalArgumentException("TopicPartition has null/blank topic: " + tp);
    }
}
consumer.assign(partitions);

Type guard

// Java: ensure every TopicPartition is well-formed
static boolean isWellFormed(TopicPartition tp) {
    return tp != null && tp.topic() != null && !tp.topic().trim().isEmpty()
        && tp.partition() >= 0;
}
// filter: partitions.removeIf(tp -> !isWellFormed(tp));

Try / catch

// Not recommended: validate before assign() rather than catching.
// If unavoidable:
try {
    consumer.assign(partitions);
} catch (IllegalArgumentException e) {
    // log, drop offending TopicPartition, or fail-fast upstream
    log.error("Invalid assignment", e);
    throw e;
}

Prevention

When it happens

Trigger: Calling consumer.assign(Arrays.asList(new TopicPartition(null, 0))), passing a TopicPartition built from an uninitialized String field, or building the collection from a stream/map that yields null or "" topic names. Any element where TopicPartition.topic() returns a blank string triggers it; a wholly null TopicPartition element also triggers it because tp.topic() would be reached only after the null check at line 1900.

Common situations: Topic name read from a misconfigured property file or environment variable that resolved to empty; deserializing partitions from JSON/YAML where a field was omitted; refactoring code that previously used String topic names and forgetting to populate the field; unit tests that construct TopicPartition placeholders.

Related errors


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