apache/kafka · error · KafkaException

The assignor name: '{assignorName}' is used in more than one

Error message

The assignor name: '{assignorName}' is used in more than one assignor: {firstClass}, {secondClass}

What it means

Thrown by ConsumerPartitionAssignor.getAssignorInstances when two distinct assignor classes registered via partition.assignment.strategy expose the same name() string. Each assignor must have a unique name because the coordinator uses the name to route the assignment protocol; a duplicate would make assignment ambiguous.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java:441

        for (Object klass : assignorClasses) {
            // first try to get the class if passed in as a string
            if (klass instanceof String) {
                try {
                    klass = Utils.loadClass((String) klass, Object.class);
                } catch (ClassNotFoundException classNotFound) {
                    throw new KafkaException(klass + " ClassNotFoundException exception occurred", classNotFound);
                }
            }

            if (klass instanceof Class<?>) {
                Object assignor = Utils.newInstance((Class<?>) klass);
                if (assignor instanceof Configurable)
                    ((Configurable) assignor).configure(configs);

                if (assignor instanceof ConsumerPartitionAssignor) {
                    String assignorName = ((ConsumerPartitionAssignor) assignor).name();
                    if (assignorNameMap.containsKey(assignorName)) {
                        throw new KafkaException("The assignor name: '" + assignorName + "' is used in more than one assignor: " +
                            assignorNameMap.get(assignorName) + ", " + assignor.getClass().getName());
                    }
                    assignorNameMap.put(assignorName, assignor.getClass().getName());
                    assignors.add((ConsumerPartitionAssignor) assignor);
                } else {
                    throw new KafkaException(klass + " is not an instance of " + ConsumerPartitionAssignor.class.getName());
                }
            } else {
                throw new KafkaException("List contains element of type " + klass.getClass().getName() + ", expected String or Class");
            }
        }
        return assignors;
    }

}

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Inspect the value of partition.assignment.strategy and remove the duplicate assignor class so each name() appears once.
  2. If you intentionally keep both classes, override name() on your custom assignor to return a unique string.
  3. Check for shaded/duplicate dependency JARs on the classpath that ship the same assignor implementation and exclude the redundant one.

Example fix

// before
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    Arrays.asList(CooperativeStickyAssignor.class.getName(), MyStickyAssignor.class.getName())); // MyStickyAssignor.name() == "cooperative-sticky"

// after
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    Collections.singletonList(CooperativeStickyAssignor.class.getName())); // or give MyStickyAssignor a unique name()
Defensive patterns

Strategy: validation

Validate before calling

// Before building the consumer: dedupe the partition.assignment.strategy entries by assignor name()
List<ConsumerPartitionAssignor> deduped = new ArrayList<>();
Set<String> seenNames = new HashSet<>();
for (Object entry : assignorList) {
    ConsumerPartitionAssignor a = instantiate(entry); // your own loader
    if (!seenNames.add(a.name())) {
        throw new IllegalStateException("Duplicate assignor name '" + a.name() + "' in partition.assignment.strategy");
    }
    deduped.add(a);
}
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
          deduped.stream().map(a -> a.getClass().getName()).collect(Collectors.toList()));

Try / catch

// Wrap consumer construction; the exception surfaces when KafkaConsumer resolves assignors
try {
    this.consumer = new KafkaConsumer<>(props);
} catch (KafkaException e) {
    if (e.getMessage() != null && e.getMessage().contains("is used in more than one assignor")) {
        // log, drop the duplicate assignor from props, and retry / fail fast
    }
    throw e;
}

Prevention

When it happens

Trigger: Listing two classes in partition.assignment.strategy whose name() collides, e.g. configuring both a custom assignor and a wrapped/cooperative variant that returns the same name, or loading the same logical assignor via two different shaded/jar copies.

Common situations: Upgrading from eager to cooperative assignors and leaving both on the classpath; bundling duplicate copies of an assignor (shaded deps); misconfigured custom assignor that hard-codes an existing name like 'range' or 'cooperative-sticky'.

Related errors


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