apache/kafka · error · KafkaException

{klass} ClassNotFoundException exception occurred

Error message

{klass} ClassNotFoundException exception occurred

What it means

Thrown by ConsumerPartitionAssignor.getAssignorInstances when Utils.loadClass fails to find the class named in partition.assignment.strategy. The client tries to resolve each configured assignor class name via the context classloader; if the class is absent from the classpath, the ClassNotFoundException is wrapped and rethrown as a KafkaException at consumer construction.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/ConsumerPartitionAssignor.java:429

        }
    }

    /**
     * Get a list of configured instances of {@link org.apache.kafka.clients.consumer.ConsumerPartitionAssignor}
     * based on the class names/types specified by {@link org.apache.kafka.clients.consumer.ConsumerConfig#PARTITION_ASSIGNMENT_STRATEGY_CONFIG}
     */
    static List<ConsumerPartitionAssignor> getAssignorInstances(List<String> assignorClasses, Map<String, Object> configs) {
        List<ConsumerPartitionAssignor> assignors = new ArrayList<>();
        // a map to store assignor name -> assignor class name
        Map<String, String> assignorNameMap = new HashMap<>();

        for (Object klass : assignorClasses) {
            // first try to get the class if passed in as a string
            if (klass instanceof String) {
                try {
                    klass = Utils.loadClass((String) klass, Object.class);
                } catch (ClassNotFoundException classNotFound) {
                    throw new KafkaException(klass + " ClassNotFoundException exception occurred", classNotFound);
                }
            }

            if (klass instanceof Class<?>) {
                Object assignor = Utils.newInstance((Class<?>) klass);
                if (assignor instanceof Configurable)
                    ((Configurable) assignor).configure(configs);

                if (assignor instanceof ConsumerPartitionAssignor) {
                    String assignorName = ((ConsumerPartitionAssignor) assignor).name();
                    if (assignorNameMap.containsKey(assignorName)) {
                        throw new KafkaException("The assignor name: '" + assignorName + "' is used in more than one assignor: " +
                            assignorNameMap.get(assignorName) + ", " + assignor.getClass().getName());
                    }
                    assignorNameMap.put(assignorName, assignor.getClass().getName());
                    assignors.add((ConsumerPartitionAssignor) assignor);
                } else {
                    throw new KafkaException(klass + " is not an instance of " + ConsumerPartitionAssignor.class.getName());

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Verify the assignor class name is the correct fully-qualified name and matches what is on the classpath.
  2. Ensure the jar containing the assignor is packaged into the deployed artifact (check the fat-jar / docker image classpath).
  3. If the assignor was removed or renamed, update partition.assignment.strategy to a valid class (e.g. org.apache.kafka.clients.consumer.CooperativeStickyAssignor).
  4. If using a shaded uber-jar, configure the shading plugin to keep the assignor's package, or update the FQCN to the shaded name.

Example fix

// before
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    "com.acme.kafka.CustomAssignor"); // not on classpath -> throws

// after (option A: ship the jar / fix FQCN)
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    "com.acme.kafka.StickyCustomAssignor"); // correct FQCN, jar present

// after (option B: fall back to a built-in assignor)
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    CooperativeStickyAssignor.class.getName());
Defensive patterns

Strategy: validation

Validate before calling

// Verify each partition.assignor class is loadable before constructing the consumer:
List<String> assignors = Arrays.asList(props.getProperty(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, "").split(","));
for (String name : assignors) {
    String trimmed = name.trim();
    if (trimmed.isEmpty()) continue;
    try {
        Class<?> cls = Class.forName(trimmed);
        if (!ConsumerPartitionAssignor.class.isAssignableFrom(cls)) {
            throw new RuntimeException(trimmed + " is not a ConsumerPartitionAssignor");
        }
    } catch (ClassNotFoundException e) {
        throw new RuntimeException("partition.assignment.strategy class not on classpath: " + trimmed, e);
    }
}

Type guard

static boolean isLoadableAssignor(String className) {
    try {
        Class<?> cls = Class.forName(className);
        return ConsumerPartitionAssignor.class.isAssignableFrom(cls);
    } catch (ClassNotFoundException e) {
        return false;
    }
}

Try / catch

try {
    new KafkaConsumer<>(props);
} catch (KafkaException e) {
    if (e.getMessage() != null && e.getMessage().contains("ClassNotFoundException")) {
        // fall back to a default assignor known to be on the classpath
        props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
                  CooperativeStickyAssignor.class.getName());
        new KafkaConsumer<>(props);
    } else throw e;
}

Prevention

When it happens

Trigger: Constructing a KafkaConsumer whose partition.assignment.strategy names a class (fully qualified) that is not on the runtime classpath — e.g. a custom assignor in a jar that was not packaged/deployed, a third-party assignor dependency that was shaded out, or a typo in the class name.

Common situations: Using a custom ConsumerPartitionAssignor whose jar is missing from the deployed artifact; fat-jar shading that renames the assignor package without updating the config; typo in the FQCN; referencing a class that exists only in a test source set from production code; deploying a stub config that names an assignor from a different product line.

Related errors


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