apache/pulsar · error · IllegalArgumentException

Cannot find/load class ${className}

Error message

Cannot find/load class ${className}

What it means

Thrown by the multi-class validator when Class.forName-style loading of the configured class name throws ClassNotFoundException. The class name string in the config field could not be resolved by the thread context classloader, so no assignment check is even possible.

Source

Thrown at pulsar-config-validation/src/main/java/org/apache/pulsar/config/validation/ValidatorImpls.java:193

        public ImplementsClassesValidator(Map<String, Object> params) {
            this.classesImplements = (Class<?>[]) params.get(
                    ConfigValidationAnnotations.ValidatorParams.IMPLEMENTS_CLASSES);
        }

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            SimpleTypeValidator.validateField(name, String.class, o);
            String className = (String) o;
            int count = 0;
            for (Class<?> classImplements : classesImplements) {
                Class<?> objectClass = null;
                try {
                    objectClass = loadClass(className);
                } catch (ClassNotFoundException e) {
                    throw new IllegalArgumentException("Cannot find/load class " + className);
                }

                if (classImplements.isAssignableFrom(objectClass)) {
                    count++;
                }
            }
            if (count == 0) {
                throw new IllegalArgumentException(
                        String.format("Field '%s' with value '%s' does not implement any of these classes %s",
                                name, o, Arrays.toString(classesImplements)));
            }
        }
    }

    /**
     * validates each key and each value against the respective arrays of validators.
     */
    public static class MapEntryCustomValidator extends Validator {

View on GitHub (pinned to 820761864e)

Solutions

  1. Correct the fully-qualified class name in the config (spelling, package, casing).
  2. Add the jar/module containing the class to the deployment classpath (e.g. Pulsar Functions' extra deps /nar or lib directory).
  3. Confirm with the same classloader that will load at runtime — Thread.currentThread().getContextClassLoader() — that Class.forName(name, true, loader) succeeds.
  4. Check for renames between library versions and update config accordingly.

Example fix

// before (config)
authPlugin = org.apache.pulsar.client.impl.auth.AutinizationToken  // typo
// after
authPlugin = org.apache.pulsar.client.impl.auth.AuthenticationToken
Defensive patterns

Strategy: validation

Validate before calling

static boolean classLoadable(String className) {
    try {
        Class.forName(className, false, Thread.currentThread().getContextClassLoader());
        return true;
    } catch (ClassNotFoundException e) {
        return false;
    }
}
// call before applying config: classLoadable(cfgValue)

Try / catch

try {
    validator.validateField("authPlugin", pluginClassName);
} catch (IllegalArgumentException e) {
    log.error("Cannot load configured class {} — check class name and classpath", pluginClassName, e);
    throw new ConfigurationException(e.getMessage(), e);
}

Prevention

When it happens

Trigger: A config field validated against several required interfaces calls loadClass(className); if the class is absent from the classpath (wrong name, missing jar, wrong package), the ClassNotFoundException is wrapped into this IllegalArgumentException.

Common situations: Typo in fully-qualified class name; dependency jar not shipped with the deployment; class exists only in test scope; class moved/renamed after an upgrade; config copied between environments with different classpaths.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/fe61745276e9aeb5. Report an issue: GitHub.