{"record":{"id":"1c54ebd557f3c8fa","repo":"apache/kafka","slug":"list-contains-element-of-type-type-expected-str","errorCode":null,"errorMessage":"List contains element of type {type}, expected String or Class","messagePattern":"List contains element of type (.+?), expected String or Class","errorType":"validation","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/996fb4585aa1bcc8980b0e1b8d6b168b986cd979/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 handle those two forms, so any other Java type is rejected immediately rather than silently ignored. This is a programming/config-construction error, not a runtime data error.","triggerScenarios":"Passing a List containing a Class instance plus a non-class object (e.g. a Map, an assignor instance, or a Path); constructing the config programmatically with mixed element types; serializing/deserializing config in a way that turns class names into typed objects.","commonSituations":"Building ConsumerConfig from a JSON/Properties source that interpreted one entry as an object; tests that hand-construct the assignor list with helper methods returning heterogeneous types; framework glue that injects pre-instantiated objects into the strategy list.","solutions":["Ensure every element of partition.assignment.strategy is either a String FQN or a Class<?> reference, not a mix.","When loading config from JSON/YAML, coerce all strategy entries to String and let Kafka load the class.","Add a unit assertion that every list element is instanceof String || instanceof Class before constructing the consumer."],"exampleFix":"// before\nList<Object> strategies = new ArrayList<>();\nstrategies.add(CooperativeStickyAssignor.class);\nstrategies.add(someAssignorInstance); // wrong type\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, strategies);\n\n// after\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,\n    List.of(CooperativeStickyAssignor.class.getName()));","handlingStrategy":"validation","validationCode":"List<String> safe = configuredStrategies.stream().map(o -> {\n    if (o instanceof String) return (String) o;\n    if (o instanceof Class<?>) return ((Class<?>) o).getName();\n    throw new IllegalArgumentException(\"partition.assignment.strategy entry is neither String nor Class: \" + o.getClass());\n}).collect(Collectors.toList());\nprops.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, safe);","typeGuard":"static boolean isStrategyEntry(Object o) {\n    return o instanceof String || o instanceof Class<?>;\n}","tryCatchPattern":"try {\n    consumer = new KafkaConsumer<>(props);\n} catch (KafkaException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"List contains element of type \")) {\n        // coerce the offending list to List<String> FQNs and rebuild props\n    }\n    throw e;\n}","preventionTips":["Always build partition.assignment.strategy as List<String> of FQNs; never mix types.","When loading config from JSON/YAML, force every strategy entry to String.","Unit-test the config builder to assert homogeneous list element types."],"tags":["consumer","partition-assignor","configuration","type-mismatch"],"backgroundTag":null,"analyzedSha":"996fb4585aa1bcc8980b0e1b8d6b168b986cd979","analyzedAt":"2026-08-11T22:03:28.655Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}