{"id":"e78eda7b994ec1c7","repo":"apache/kafka","slug":"list-contains-element-of-type-classname-expecte","errorCode":null,"errorMessage":"List contains element of type {className}, expected String or Class","messagePattern":"List contains element of type (.+?), expected String or Class","errorType":"exception","errorClass":"KafkaException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java","lineNumber":450,"sourceCode":"\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":432,"sourceCodeEnd":457,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java#L432-L457","documentation":"Thrown by ConsumerPartitionAssignor.getAssignorInstances when an element of the partition.assignment.strategy list is neither a String (class name) nor a Class object. The loader only knows how to materialize assignors from those two element types.","triggerScenarios":"Building partition.assignment.strategy programmatically and pushing a non-string, non-Class value such as an instance object, an int, or a Properties map into the list; mis-typed JSON/Properties parsing that yields an Object instead of a String.","commonSituations":"Passing already-instantiated assignor instances instead of class names; reading config from JSON/YAML where numbers/booleans leak into the list; reflection-based config injection with the wrong element type.","solutions":["Ensure each element of partition.assignment.strategy is a String (class name) or a Class<?> literal.","If you have instances, pass their class names via assignor.getClass().getName() instead of the instance objects.","Sanitize external config sources so the strategy list is parsed as a list of strings."],"exampleFix":"// before\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,\n    Arrays.asList(new CooperativeStickyAssignor())); // instance, not a name\n\n// after\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,\n    Arrays.asList(CooperativeStickyAssignor.class.getName()));","handlingStrategy":"type-guard","validationCode":"// partition.assignment.strategy must contain only String (class name) or Class elements\nfor (Object entry : (List<?>) props.get(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG)) {\n    if (!(entry instanceof String) && !(entry instanceof Class<?>)) {\n        throw new IllegalArgumentException(\"Invalid element type \" + entry.getClass().getName()\n            + \" in partition.assignment.strategy; expected String or Class\");\n    }\n}","typeGuard":"static boolean isValidAssignorEntry(Object entry) {\n    return entry instanceof String || entry instanceof Class<?>;\n}","tryCatchPattern":"try {\n    new KafkaConsumer<>(props);\n} catch (KafkaException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"expected String or Class\")) {\n        // rebuild the list with only String entries (class names) and retry\n    }\n    throw e;\n}","preventionTips":["Always specify partition.assignment.strategy as a List<String> of fully-qualified class names — never raw objects.","Avoid reusing a generic List<Object> that may have been polluted with other types.","Validate the list contents immediately after deserializing props from JSON/YAML config files."],"tags":["consumer","partition-assignor","configuration","type-mismatch"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}