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
- 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.
- If you do not need group management, call assign(Collection<TopicPartition>) instead of subscribe(...); manual assignment does not require an assignor.
- 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
- Never set partition.assignment.strategy to an empty string.
- If overriding the default, include at least one known-good class (RangeAssignor, CooperativeStickyAssignor, StickyAssignor).
- Validate the consumer config against a known schema at startup before constructing the consumer.
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
- Specified assignors {} do not have commonly supported rebala
- Invalid value null for configuration key.deserializer: must
- Invalid value null for configuration value.deserializer: mus
- enable.auto.commit cannot be set to true when default group
- {invalidConfigs} cannot be set when group.protocol={groupPro
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/2d768c518ebd4279.json.
Report an issue: GitHub.