apache/kafka · error · KafkaException

List contains element of type {className}, expected String o

Error message

List contains element of type {className}, expected String or Class

What it means

Thrown by ConsumerPartitionAssignor.getAssignorInstances when an element of the partition.assignment.strategy list is neither a String (class name) nor a Class object. The loader only knows how to materialize assignors from those two element types.

Source

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

            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());
                }
            } else {
                throw new KafkaException("List contains element of type " + klass.getClass().getName() + ", expected String or Class");
            }
        }
        return assignors;
    }

}

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Ensure each element of partition.assignment.strategy is a String (class name) or a Class<?> literal.
  2. If you have instances, pass their class names via assignor.getClass().getName() instead of the instance objects.
  3. Sanitize external config sources so the strategy list is parsed as a list of strings.

Example fix

// before
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    Arrays.asList(new CooperativeStickyAssignor())); // instance, not a name

// after
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
    Arrays.asList(CooperativeStickyAssignor.class.getName()));
Defensive patterns

Strategy: type-guard

Validate before calling

// partition.assignment.strategy must contain only String (class name) or Class elements
for (Object entry : (List<?>) props.get(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG)) {
    if (!(entry instanceof String) && !(entry instanceof Class<?>)) {
        throw new IllegalArgumentException("Invalid element type " + entry.getClass().getName()
            + " in partition.assignment.strategy; expected String or Class");
    }
}

Type guard

static boolean isValidAssignorEntry(Object entry) {
    return entry instanceof String || entry instanceof Class<?>;
}

Try / catch

try {
    new KafkaConsumer<>(props);
} catch (KafkaException e) {
    if (e.getMessage() != null && e.getMessage().contains("expected String or Class")) {
        // rebuild the list with only String entries (class names) and retry
    }
    throw e;
}

Prevention

When it happens

Trigger: Building partition.assignment.strategy programmatically and pushing a non-string, non-Class value such as an instance object, an int, or a Properties map into the list; mis-typed JSON/Properties parsing that yields an Object instead of a String.

Common situations: Passing already-instantiated assignor instances instead of class names; reading config from JSON/YAML where numbers/booleans leak into the list; reflection-based config injection with the wrong element type.

Related errors


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