apache/pulsar · error · RuntimeException

(wraps reflective instantiation failure for interceptor)

Error message

(wraps reflective instantiation failure for interceptor)

What it means

BrokerEntryMetadataUtils.loadInterceptors loads and reflectively instantiates generic interceptor classes by name. Any InstantiationException, IllegalAccessException, InvocationTargetException, or NoSuchMethodException during construction is logged and rethrown as RuntimeException.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/intercept/BrokerEntryMetadataUtils.java:81

    }
    public static <T> Set<T> loadInterceptors(
            Set<String> interceptorNames, ClassLoader classLoader) {
        Set<T> interceptors = new LinkedHashSet<>();
        if (interceptorNames != null && interceptorNames.size() > 0) {
            for (String interceptorName : interceptorNames) {
                try {
                    @SuppressWarnings("unchecked") // class is loaded by name and expected to match type T
                    Class<T> clz = (Class<T>) ClassLoaderUtils
                        .loadClass(interceptorName, classLoader);
                    try {
                        interceptors.add(clz.getDeclaredConstructor().newInstance());
                    } catch (InstantiationException | IllegalAccessException
                        | InvocationTargetException | NoSuchMethodException e) {
                        log.error()
                            .attr("interceptorName", interceptorName)
                            .exception(e)
                            .log("Create new instance failed.");
                        throw new RuntimeException(e);
                    }
                } catch (ClassNotFoundException e) {
                    log.error()
                        .attr("interceptorName", interceptorName)
                        .exception(e)
                        .log("Load class failed.");
                    throw new RuntimeException(e);
                }
            }
        }
        return interceptors;
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Add a public no-arg constructor to the interceptor and make the class concrete/public
  2. Fix any exception thrown inside the interceptor's constructor (check the wrapped InvocationTargetException cause)
  3. Ensure the class and constructor are public so reflection can access them

Example fix

// before
public class MyInterceptor implements BrokerEntryMetadataInterceptor {
    private MyInterceptor() {}
}
// after
public class MyInterceptor implements BrokerEntryMetadataInterceptor {
    public MyInterceptor() {}
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(interceptorName);
if (Modifier.isAbstract(c.getModifiers())) {
    throw new IllegalArgumentException("Interceptor cannot be abstract: " + interceptorName);
}
Constructor<?> ctor = c.getDeclaredConstructor();
ctor.setAccessible(true);
ctor.newInstance(); // dry-run: surfaces InvocationTargetException early

Try / catch

try {
    interceptors = BrokerEntryMetadataUtils.loadInterceptors(names, cl, Interceptor.class);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    log.error("Interceptor {} could not be instantiated: {}", names, cause == null ? e : cause.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Configured interceptor class is abstract, lacks an accessible no-arg constructor, or its constructor throws during execution, when calling loadInterceptors with an interceptor name.

Common situations: Custom interceptor implementations that define only parameterized constructors, constructors that throw in initialization code, classes not designed to be reflectively instantiated.

Related errors


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