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 implement

View on GitHub (pinned to c31c9215e1)

Solutions

  1. 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.
  2. If a config provider / external source is returning typed objects, convert them to class-name strings before they reach getConfiguredInstance.
  3. Audit the list/element source (the message reports the actual Java type via klass.getClass().getName()) and fix the producer of that list.
  4. 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

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


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/71c2f8ec12adc991.json. Report an issue: GitHub.