apache/pulsar · error · IllegalArgumentException
Field '${name}' with value '${o}' does not implement ${class
Error message
Field '${name}' with value '${o}' does not implement ${classImplements.getName()} What it means
This IllegalArgumentException is thrown by a class-assignment validator during config validation. It first coerces the value to a String, loads the named class via the thread context classloader, and checks that the class is assignable to the interface/class the validator was constructed with. If the class loads but does not implement/extend the required type, validation of the field fails with this message.
Source
Thrown at pulsar-config-validation/src/main/java/org/apache/pulsar/config/validation/ValidatorImpls.java:158
this.classImplements = (Class<?>) params.get(ConfigValidationAnnotations.ValidatorParams.IMPLEMENTS_CLASS);
}
public ImplementsClassValidator(Class<?> classImplements) {
this.classImplements = classImplements;
}
@Override
public void validateField(String name, Object o) {
if (o == null) {
return;
}
SimpleTypeValidator.validateField(name, String.class, o);
String className = (String) o;
try {
ClassLoader clsLoader = Thread.currentThread().getContextClassLoader();
Class<?> objectClass = clsLoader.loadClass(className);
if (!this.classImplements.isAssignableFrom(objectClass)) {
throw new IllegalArgumentException(
String.format("Field '%s' with value '%s' does not implement %s ",
name, o, this.classImplements.getName()));
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
/**
* validates class implements one of these classes.
*/
public static class ImplementsClassesValidator extends Validator {
Class<?>[] classesImplements;
public ImplementsClassesValidator(Map<String, Object> params) {
this.classesImplements = (Class<?>[]) params.get(View on GitHub (pinned to 820761864e)
Solutions
- Make the configured class implement/extend the required interface (check the interface name in the message) and rebuild/redeploy it.
- Verify the fully-qualified class name in the config is the correct implementation, not a similar-looking class.
- Check for duplicate/old jars on the classpath so the loaded version of the class actually implements the interface.
- Pre-validate the class before writing it into config (see validationCode).
Example fix
// before: config value that does not implement the interface
myCodec = com.example.PlainObject // PlainObject does not implement Codec
// after
myCodec = com.example.MyCodecImpl // class MyCodecImpl implements Codec {} Defensive patterns
Strategy: validation
Validate before calling
boolean implementsRequired(String className, Class<?> required) {
try {
Class<?> c = Class.forName(className, false,
Thread.currentThread().getContextClassLoader());
return required.isAssignableFrom(c);
} catch (ClassNotFoundException e) {
return false;
}
}
// call before setting config: implementsRequired("com.example.MyCodec", Codec.class) Try / catch
try {
validator.validateField("myCodec", className);
} catch (IllegalArgumentException e) {
log.error("Configured class {} does not implement the required interface", className, e);
throw new ConfigurationException(e.getMessage(), e);
} Prevention
- Add a startup smoke test that validates all class-name config fields before service traffic.
- Keep implementation and interface in the same shipped artifact to avoid version skew.
- Document the required interface next to each class-name config key.
- Run ./gradlew sanityCheck or equivalent to catch classpath drift early.
When it happens
Trigger: A config field validated with a ClassValidator constructed as new ClassValidator(SomeInterface.class) is set to a class name (e.g. "com.example.MyCodec") whose loaded Class object fails the SomeInterface.class.isAssignableFrom check — i.e. the class exists but does not implement the required interface.
Common situations: Typo-ed or stale config pointing at a class that used to implement the interface but was refactored; user supplies a concrete class instead of an implementation of the required interface; multiple versions of a jar on the classpath where the deployed version lacks the interface.
Related errors
- Cannot find/load class ${className}
- Field '${name}' with value '${o}' does not implement any of
- Field ${name} is not an accepted value. Value: ${o} Accepted
- configuredService should not be an instance of SystemTopicBa
- Segment not found
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/40440253c24015e2.
Report an issue: GitHub.