apache/kafka · error · IllegalStateException

Must configure at least one partition assigner class name to

Error message

Must configure at least one partition assigner class name to {} configuration property

What it means

IllegalStateException thrown by ClassicKafkaConsumer.throwIfNoAssignorsConfigured() (ClassicKafkaConsumer.java:1272) when subscribe(Collection) or subscribe(Pattern) is called and the assignor list ended up empty. The assignor list is built from the partition.assignment.strategy config (default RangeAssignor + CooperativeStickyAssignor); if the user explicitly sets it blank or supplies only class names that fail to instantiate/are filtered out, no strategy remains to compute partitions for the group, so the library refuses to subscribe.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/ClassicKafkaConsumer.java:1274

        if (threadId != currentThread.get() && !currentThread.compareAndSet(NO_CURRENT_THREAD, threadId))
            throw new ConcurrentModificationException("KafkaConsumer is not safe for multi-threaded access. " +
                    "currentThread(name: " + thread.getName() + ", id: " + threadId + ")" +
                    " otherThread(id: " + currentThread.get() + ")"
            );
        refcount.incrementAndGet();
    }

    /**
     * Release the light lock protecting the consumer from multi-threaded access.
     */
    private void release() {
        if (refcount.decrementAndGet() == 0)
            currentThread.set(NO_CURRENT_THREAD);
    }

    private void throwIfNoAssignorsConfigured() {
        if (assignors.isEmpty())
            throw new IllegalStateException("Must configure at least one partition assigner class name to " +
                    ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG + " configuration property");
    }

    private void throwIfGroupIdNotDefined() {
        if (groupId.isEmpty())
            throw new InvalidGroupIdException("To use the group management or offset commit APIs, you must " +
                    "provide a valid " + ConsumerConfig.GROUP_ID_CONFIG + " in the consumer configuration.");
    }

    private void updateLastSeenEpochIfNewer(TopicPartition topicPartition, OffsetAndMetadata offsetAndMetadata) {
        if (offsetAndMetadata != null)
            offsetAndMetadata.leaderEpoch().ifPresent(epoch -> metadata.updateLastSeenEpochIfNewer(topicPartition, epoch));
    }

    // Functions below are for testing only
    @Override
    public String clientId() {
        return clientId;

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Set partition.assignment.strategy to at least one valid ConsumerPartitionAssignor class name (e.g. org.apache.kafka.clients.consumer.CooperativeStickyAssignor), or simply omit the property to take the defaults.
  2. If you do not need group management, call assign(Collection<TopicPartition>) instead of subscribe(...); manual assignment does not require an assignor.
  3. For custom assignors, confirm the class is on the classpath, has a public no-arg constructor, and that its name() does not collide with a built-in.

Example fix

// before
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, "");
consumer.subscribe(Arrays.asList("orders"));   // throws IllegalStateException

// after — pick a real assignor, or use manual assignment
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    CooperativeStickyAssignor.class.getName());
consumer.subscribe(Arrays.asList("orders"));

// or, if group management is not required:
consumer.assign(Arrays.asList(new TopicPartition("orders", 0)));
Defensive patterns

Strategy: validation

Validate before calling

// Ensure at least one partition assignor is configured before subscribe()
String assignors = props.getProperty(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG);
if (assignors != null && assignors.trim().isEmpty()) {
    // empty value is the dangerous case; drop it to fall back to the default RangeAssignor
    props.remove(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG);
}

Try / catch

try {
    consumer.subscribe(topics);
} catch (IllegalStateException e) {
    // partition.assignment.strategy was blanked/invalid; reconfigure and rebuild
    props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
              RangeAssignor.class.getName());
    consumer = new KafkaConsumer<>(props);
}

Prevention

When it happens

Trigger: Calling subscribe(Collection<String>) or subscribe(Pattern) on a consumer whose partition.assignment.strategy resolved to no usable assignor. The check fires from subscribeInternal at ClassicKafkaConsumer.java:506 (topic list) and :582 (pattern).

Common situations: Copy-pasting config and dropping the default assignors; intentionally disabling group management by setting partition.assignment.strategy to an empty string but still calling subscribe(); a custom ConsumerPartitionAssignor class missing from the classpath and silently dropped during instantiation; YAML/env interpolation (e.g. ${ASSIGNORS:-} expanding to empty).

Related errors


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