{"id":"812e0c2a563a0f39","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: {firstClass}, {secondClass}","messagePattern":"The assignor name: '(.+?)' is used in more than one assignor: (.+?), (.+?)","errorType":"exception","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/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java#L423-L457","documentation":"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.","triggerScenarios":"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.","commonSituations":"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'.","solutions":["Inspect the value of partition.assignment.strategy and remove the duplicate assignor class so each name() appears once.","If you intentionally keep both classes, override name() on your custom assignor to return a unique string.","Check for shaded/duplicate dependency JARs on the classpath that ship the same assignor implementation and exclude the redundant one."],"exampleFix":"// before\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,\n    Arrays.asList(CooperativeStickyAssignor.class.getName(), MyStickyAssignor.class.getName())); // MyStickyAssignor.name() == \"cooperative-sticky\"\n\n// after\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,\n    Collections.singletonList(CooperativeStickyAssignor.class.getName())); // or give MyStickyAssignor a unique name()","handlingStrategy":"validation","validationCode":"// Before building the consumer: dedupe the partition.assignment.strategy entries by assignor name()\nList<ConsumerPartitionAssignor> deduped = new ArrayList<>();\nSet<String> seenNames = new HashSet<>();\nfor (Object entry : assignorList) {\n    ConsumerPartitionAssignor a = instantiate(entry); // your own loader\n    if (!seenNames.add(a.name())) {\n        throw new IllegalStateException(\"Duplicate assignor name '\" + a.name() + \"' in partition.assignment.strategy\");\n    }\n    deduped.add(a);\n}\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,\n          deduped.stream().map(a -> a.getClass().getName()).collect(Collectors.toList()));","typeGuard":null,"tryCatchPattern":"// Wrap consumer construction; the exception surfaces when KafkaConsumer resolves assignors\ntry {\n    this.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, drop the duplicate assignor from props, and retry / fail fast\n    }\n    throw e;\n}","preventionTips":["Keep partition.assignment.strategy as a short, hand-curated list; do not merge multiple assignor lists blindly.","Every ConsumerPartitionAssignor must return a unique name() — audit custom assignors before registering them.","Do not list both a cooperative and an eager variant that happen to share the same name() string.","If you must combine assignors, run them through a name-dedupe step before handing the list to KafkaConsumer."],"tags":["consumer","partition-assignor","configuration","duplicate"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}