{"record":{"id":"d5b9af6a9260b9c8","repo":"apache/kafka","slug":"the-assignor-name-assignorname-is-used-in-mor","errorCode":null,"errorMessage":"The assignor name: '{assignorName}' is used in more than one assignor: {existing}, {current}","messagePattern":"The assignor name: '(.+?)' is used in more than one assignor: (.+?), (.+?)","errorType":"validation","errorClass":"KafkaException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java","lineNumber":441,"sourceCode":"        for (Object klass : assignorClasses) {\n            // first try to get the class if passed in as a string\n            if (klass instanceof String) {\n                try {\n                    klass = Utils.loadClass((String) klass, Object.class);\n                } catch (ClassNotFoundException classNotFound) {\n                    throw new KafkaException(klass + \" ClassNotFoundException exception occurred\", classNotFound);\n                }\n            }\n\n            if (klass instanceof Class<?>) {\n                Object assignor = Utils.newInstance((Class<?>) klass);\n                if (assignor instanceof Configurable)\n                    ((Configurable) assignor).configure(configs);\n\n                if (assignor instanceof ConsumerPartitionAssignor) {\n                    String assignorName = ((ConsumerPartitionAssignor) assignor).name();\n                    if (assignorNameMap.containsKey(assignorName)) {\n                        throw new KafkaException(\"The assignor name: '\" + assignorName + \"' is used in more than one assignor: \" +\n                            assignorNameMap.get(assignorName) + \", \" + assignor.getClass().getName());\n                    }\n                    assignorNameMap.put(assignorName, assignor.getClass().getName());\n                    assignors.add((ConsumerPartitionAssignor) assignor);\n                } else {\n                    throw new KafkaException(klass + \" is not an instance of \" + ConsumerPartitionAssignor.class.getName());\n                }\n            } else {\n                throw new KafkaException(\"List contains element of type \" + klass.getClass().getName() + \", expected String or Class\");\n            }\n        }\n        return assignors;\n    }\n\n}\n","sourceCodeStart":423,"sourceCodeEnd":457,"githubUrl":"https://github.com/apache/kafka/blob/996fb4585aa1bcc8980b0e1b8d6b168b986cd979/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java#L423-L457","documentation":"Thrown by ConsumerPartitionAssignor.getAssignorInstances while building the partition assignor list from the 'partition.assignment.strategy' consumer config. Each assignor exposes a name() string; Kafka requires these names to be unique within one consumer because the assignor name is used as a protocol identifier during the JoinGroup. Two entries in the config whose classes return the same name() collide, and construction aborts before the consumer starts.","triggerScenarios":"Listing the same class twice in partition.assignment.strategy (e.g. [org.apache.kafka.clients.consumer.CooperativeStickyAssignor, org.apache.kafka.clients.consumer.CooperativeStickyAssignor]); listing two different custom assignors whose name() methods return the same literal; wrapping/decorating an existing assignor but forgetting to override name(); upgrading to a Kafka version where a built-in assignor's name() changed and now matches another one you configured.","commonSituations":"Migrating from eager to cooperative assignors and leaving both StickyAssignor and CooperativeStickyAssignor in the list; copy-paste of a custom assignor class with a duplicated name field; fat-jar shading that bundles two versions of an assignor; mixing a third-party assignor with a built-in one that shares its name.","solutions":["Inspect the full partition.assignment.strategy value and remove duplicate class entries or classes that share a name().","If you ship a custom assignor, verify its name() returns a unique string distinct from org.apache.kafka.clients.consumer.* defaults (range, roundrobin, sticky, cooperative-sticky).","Read the error's {existing} and {current} class names to see exactly which two classes collide, then drop one from the config.","When wrapping an assignor, override name() to a new value rather than delegating to the wrapped instance."],"exampleFix":"// before\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,\n    List.of(CooperativeStickyAssignor.class.getName(),\n            CooperativeStickyAssignor.class.getName())); // duplicated\n\n// after\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,\n    List.of(CooperativeStickyAssignor.class.getName()));","handlingStrategy":"validation","validationCode":"// before building the consumer, validate assignor names are unique\nList<ConsumerPartitionAssignor> probes = configuredStrategies.stream()\n    .map(s -> { try { return (ConsumerPartitionAssignor) Utils.newInstance(Utils.loadClass(s, Object.class)); }\n               catch (ClassNotFoundException e) { throw new IllegalStateException(\"Unknown assignor class \" + s, e); } })\n    .collect(Collectors.toList());\nSet<String> names = new HashSet<>();\nfor (ConsumerPartitionAssignor a : probes) {\n    if (!names.add(a.name()))\n        throw new IllegalStateException(\"Duplicate assignor name: \" + a.name());\n}","typeGuard":"// n/a: validated at config-load time via the probe above","tryCatchPattern":"try {\n    consumer = new KafkaConsumer<>(props);\n} catch (KafkaException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"is used in more than one assignor\")) {\n        // log, dedupe partition.assignment.strategy, and fail fast with a clear config error\n    }\n    throw e;\n}","preventionTips":["Centralize partition.assignment.strategy in one config builder and add a uniqueness check on the resolved assignor names.","For custom assignors, write a unit test asserting name() returns a unique constant.","Avoid listing both eager and cooperative assignors in the same list during migrations; follow the documented order."],"tags":["consumer","partition-assignor","configuration","startup"],"backgroundTag":null,"analyzedSha":"996fb4585aa1bcc8980b0e1b8d6b168b986cd979","analyzedAt":"2026-08-11T22:03:28.655Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}