apache/kafka · error · ConfigException
Expected a Class instance or class name.
Error message
Expected a Class instance or class name.
What it means
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.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/config/ConfigDef.java:784
else
throw new ConfigException(name, value, "Expected value to be a double, but it was a " + value.getClass().getName());
case LIST:
if (value instanceof List)
return value;
else if (value instanceof String)
if (trimmed.isEmpty())
return List.of();
else
return Arrays.asList(COMMA_WITH_WHITESPACE.split(trimmed, -1));
else
throw new ConfigException(name, value, "Expected a comma separated list.");
case CLASS:
if (value instanceof Class)
return value;
else if (value instanceof String) {
return Utils.loadClass(trimmed, Object.class);
} else
throw new ConfigException(name, value, "Expected a Class instance or class name.");
default:
throw new IllegalStateException("Unknown type.");
}
} catch (NumberFormatException e) {
throw new ConfigException(name, value, "Not a number of type " + type);
} catch (ClassNotFoundException e) {
throw new ConfigException(name, value, "Class " + value + " could not be found.");
}
}
/**
* Convert the provided object into a string based on its type.
* <p>
* This method uses Java's {@link #toString()} for {@link Type#BOOLEAN}, {@link Type#SHORT}, {@link Type#INT},
* {@link Type#LONG}, {@link Type#DOUBLE}, {@link Type#STRING} and {@link Type#PASSWORD} objects.
* For {@link Type#LIST} objects, Java's {@link #toString()} is used for each entry and entries are concatenated
* separated by commas. For {@link Type#CLASS} objects, {@link Class#getName()} is used.
* @param parsedValue The object to convert into a stringView on GitHub (pinned to c31c9215e1)
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.
Example fix
// before
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
new StringSerializer()); // instance -> ConfigException
// after
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
StringSerializer.class.getName()); // FQCN
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
StringSerializer.class); // Class object Defensive patterns
Strategy: type-guard
Validate before calling
Object v = rawValue;
if (!(v instanceof Class) && !(v instanceof String)) {
throw new IllegalArgumentException("config '" + key + "' must be a Class instance or fully-qualified class name");
} Type guard
public static boolean isClassValue(Object v) {
return v instanceof Class || v instanceof String;
} Try / catch
try {
configDef.parse(configs);
} catch (ConfigException e) {
if (e.getMessage().contains("Expected a Class instance or class name")) {
// replace the value with a class name string and retry
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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()).
Common situations: 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.
Related errors
- Class value could not be found.
- Expected value to be a 64-bit integer (long), but it was a v
- Expected value to be a double, but it was a value.getClass()
- Expected a comma separated list.
- Invalid url in bootstrap.servers: {url}
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/9d3178cdd580b7fa.json.
Report an issue: GitHub.