{"id":"9d3178cdd580b7fa","repo":"apache/kafka","slug":"expected-a-class-instance-or-class-name","errorCode":null,"errorMessage":"Expected a Class instance or class name.","messagePattern":"Expected a Class instance or class name\\.","errorType":"validation","errorClass":"ConfigException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java","lineNumber":784,"sourceCode":"                    else\n                        throw new ConfigException(name, value, \"Expected value to be a double, but it was a \" + value.getClass().getName());\n                case LIST:\n                    if (value instanceof List)\n                        return value;\n                    else if (value instanceof String)\n                        if (trimmed.isEmpty())\n                            return List.of();\n                        else\n                            return Arrays.asList(COMMA_WITH_WHITESPACE.split(trimmed, -1));\n                    else\n                        throw new ConfigException(name, value, \"Expected a comma separated list.\");\n                case CLASS:\n                    if (value instanceof Class)\n                        return value;\n                    else if (value instanceof String) {\n                        return Utils.loadClass(trimmed, Object.class);\n                    } else\n                        throw new ConfigException(name, value, \"Expected a Class instance or class name.\");\n                default:\n                    throw new IllegalStateException(\"Unknown type.\");\n            }\n        } catch (NumberFormatException e) {\n            throw new ConfigException(name, value, \"Not a number of type \" + type);\n        } catch (ClassNotFoundException e) {\n            throw new ConfigException(name, value, \"Class \" + value + \" could not be found.\");\n        }\n    }\n\n    /**\n     * Convert the provided object into a string based on its type.\n     * <p>\n     * This method uses Java's {@link #toString()} for {@link Type#BOOLEAN}, {@link Type#SHORT}, {@link Type#INT},\n     * {@link Type#LONG}, {@link Type#DOUBLE}, {@link Type#STRING} and {@link Type#PASSWORD} objects.\n     * For {@link Type#LIST} objects, Java's {@link #toString()} is used for each entry and entries are concatenated\n     * separated by commas. For {@link Type#CLASS} objects, {@link Class#getName()} is used.\n     * @param parsedValue The object to convert into a string","sourceCodeStart":766,"sourceCodeEnd":802,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java#L766-L802","documentation":"Thrown by the Type.CLASS branch of ConfigDef.parseType when the value is neither a java.lang.Class nor a String. CLASS-typed configs (e.g. partitioner.class, key.serializer, value.deserializer, metric.reporters entries, client.dns.lookup via older paths, security.providers) are accepted as an actual Class object or as a fully-qualified class name string loaded via Utils.loadClass. Any other type (instance object, Map, Number) is rejected so that class loading is never attempted on garbage input.","triggerScenarios":"Constructing a producer/consumer/admin with a CLASS-typed config key set to an instance rather than the Class or class name — e.g. props.put(\"key.serializer\", new MySerializer()) instead of props.put(\"key.serializer\", MySerializer.class.getName()).","commonSituations":"New users confusing the serializer/deserializer instance with its class; DI frameworks that auto-wire an instance where the property expects the Class name; copy-pasting a bean reference instead of the FQCN; Spring Boot @Bean returning an instance injected into a Kafka property that wants a class name string.","solutions":["Set the property to the fully-qualified class name string (e.g. props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, MySerializer.class.getName())).","Or set it to a Class<?> object (e.g. props.put(..., MySerializer.class)).","Make sure the class is public, has a public no-arg constructor, and is on the classpath (otherwise error 345 follows).","If using Spring, prefer InitializingBean/Autowired approach or use DefaultKafkaProducerFactory which accepts the serializer instance directly rather than going through the class name property."],"exampleFix":"// before\nprops.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,\n         new StringSerializer()); // instance -> ConfigException\n\n// after\nprops.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,\n         StringSerializer.class.getName()); // FQCN\nprops.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,\n         StringSerializer.class); // Class object","handlingStrategy":"type-guard","validationCode":"Object v = rawValue;\nif (!(v instanceof Class) && !(v instanceof String)) {\n    throw new IllegalArgumentException(\"config '\" + key + \"' must be a Class instance or fully-qualified class name\");\n}","typeGuard":"public static boolean isClassValue(Object v) {\n    return v instanceof Class || v instanceof String;\n}","tryCatchPattern":"try {\n    configDef.parse(configs);\n} catch (ConfigException e) {\n    if (e.getMessage().contains(\"Expected a Class instance or class name\")) {\n        // replace the value with a class name string and retry\n    } else throw e;\n}","preventionTips":["For CLASS config, pass the Class object directly (e.g. MyDeserializer.class) when possible.","If only a string is available, validate it is a non-empty, fully-qualified class name before submitting."],"tags":["config","type-mismatch","serializer","class-loading","client"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}