apache/kafka · error · KafkaException
Unexpected element of type klass.getClass().getName(), expec
Error message
Unexpected element of type klass.getClass().getName(), expected String or Class
What it means
KafkaException thrown by getConfiguredInstance(Object klass, Class<T> t, ...) when the `klass` argument is neither a String (class name) nor a Class<?> object. The method only knows how to instantiate from those two forms; any other Java type (e.g. a pre-instantiated object, a Map, an Integer) is rejected. This guard runs before any reflection, so it indicates a caller passing the wrong kind of value into the instance-resolution machinery.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/config/AbstractConfig.java:413
log.info("These configurations '{}' were supplied but are not used yet.", unusedKeys);
}
}
private <T> T getConfiguredInstance(Object klass, Class<T> t, Map<String, Object> configPairs) {
if (klass == null)
return null;
Object o;
if (klass instanceof String) {
try {
o = Utils.newInstance((String) klass, t);
} catch (ClassNotFoundException e) {
throw new KafkaException("Class " + klass + " cannot be found", e);
}
} else if (klass instanceof Class<?>) {
o = Utils.newInstance((Class<?>) klass);
} else
throw new KafkaException("Unexpected element of type " + klass.getClass().getName() + ", expected String or Class");
try {
if (!t.isInstance(o))
throw new KafkaException(klass + " is not an instance of " + t.getName());
if (o instanceof Configurable)
((Configurable) o).configure(configPairs);
} catch (Exception e) {
maybeClose(o, "AutoCloseable object constructed and configured during failed call to getConfiguredInstance");
throw e;
}
return t.cast(o);
}
/**
* Get a configured instance of the give class specified by the given configuration key. If the object implements
* Configurable configure it using the configuration.
*
* @param key The configuration key for the class
* @param t The interface the class should implementView on GitHub (pinned to c31c9215e1)
Solutions
- Ensure the value passed for a class-name config is a String (FQCN) or a Class<?>; for getConfiguredInstances the list elements must all be Strings.
- If a config provider / external source is returning typed objects, convert them to class-name strings before they reach getConfiguredInstance.
- Audit the list/element source (the message reports the actual Java type via klass.getClass().getName()) and fix the producer of that list.
- Avoid passing pre-instantiated objects where the API expects a class name; register the class name instead.
Example fix
// before: list contains a non-String element
List<Object> elems = Arrays.asList("com.foo.A", alreadyConstructedObject);
config.getConfiguredInstances(elems, Plugin.class, Map.of()); // throws: type of the object
// after
List<String> elems = Arrays.asList("com.foo.A", "com.foo.B");
config.getConfiguredInstances(elems, Plugin.class, Map.of()); Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the configured value is a String (class name) or a Class<?> before passing it in.
Object configured = config.get(key);
if (configured != null && !(configured instanceof String) && !(configured instanceof Class<?>)) {
throw new IllegalArgumentException(
"Config '" + key + "' must be a class name (String) or Class<?>, got " + configured.getClass().getName());
} Type guard
boolean isClassNameOrClass(Object v) {
return v == null || v instanceof String || v instanceof Class<?>;
} Try / catch
try {
T plugin = config.getConfiguredInstance(key, T.class);
} catch (org.apache.kafka.common.KafkaException ke) {
if (ke.getMessage().contains("expected String or Class")) {
// someone put an instance / numeric / boolean into a class-name config slot
log.error("Config '{}' is {}; expected FQCN or Class", key, config.get(key).getClass());
} else {
throw ke;
}
} Prevention
- Define pluggable settings in your ConfigDef with Type.CLASS or Type.STRING so parsed values are always a Class or FQCN string.
- Never stash a pre-built instance into the config map expecting Kafka to accept it.
- Validate at config-load time when the value originates from an untrusted source (e.g. env vars, REST API).
When it happens
Trigger: Most realistic path is getConfiguredInstances(List<String> classNames, ...) where the list unexpectedly contains a non-String element (e.g. a List<Object> built from heterogeneous config, or a parsed JSON array mixing types), causing the per-element dispatch to fall into the `else` branch. Also possible when application code calls the package-private getConfiguredInstance directly with an arbitrary object.
Common situations: See trigger scenarios.
Related errors
- Unknown configuration '%s'
- Non-string value found in original settings for key entry.ge
- klass is not an instance of t.getName()
- lz4 doesn't support given compression level: level
- zstd doesn't support given compression level: level
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/71c2f8ec12adc991.json.
Report an issue: GitHub.