apache/pulsar · error · RuntimeException

(wraps reflective instantiation failure for BrokerEntryMetad

Error message

(wraps reflective instantiation failure for BrokerEntryMetadataInterceptor)

What it means

BrokerEntryMetadataUtils.loadBrokerEntryMetadataInterceptors instantiates a named BrokerEntryMetadataInterceptor class reflectively. If instantiation fails (abstract class, no no-arg constructor, inaccessible constructor), the checked reflection exceptions are logged and wrapped in a RuntimeException.

Source

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

    public static Set<BrokerEntryMetadataInterceptor> loadBrokerEntryMetadataInterceptors(
            Set<String> interceptorNames, ClassLoader classLoader) {
        Set<BrokerEntryMetadataInterceptor> interceptors = new HashSet<>();
        if (interceptorNames != null && interceptorNames.size() > 0) {
            for (String interceptorName : interceptorNames) {
                try {
                    @SuppressWarnings("unchecked") // class is loaded by name and expected to implement the interface
                    Class<BrokerEntryMetadataInterceptor> clz = (Class<BrokerEntryMetadataInterceptor>) 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 BrokerEntryMetadataInterceptor instance failed.");
                        throw new RuntimeException(e);
                    }
                } catch (ClassNotFoundException e) {
                    log.error()
                            .attr("interceptorName", interceptorName)
                            .exception(e)
                            .log("Load BrokerEntryMetadataInterceptor class failed.");
                    throw new RuntimeException(e);
                }
            }
        }
        return interceptors;
    }
    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 {

View on GitHub (pinned to 820761864e)

Solutions

  1. Ensure the interceptor class has a public no-arg constructor and is concrete
  2. Verify the class name in brokerEntryMetadataInterceptors matches a class present on the broker classpath
  3. Check the broker log line 'Create new BrokerEntryMetadataInterceptor instance failed.' for the underlying cause

Example fix

// before
class MyInterceptor implements BrokerEntryMetadataInterceptor {
    MyInterceptor(String arg) { ... }
}
// after
class MyInterceptor implements BrokerEntryMetadataInterceptor {
    public MyInterceptor() { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(interceptorName);
if (Modifier.isAbstract(c.getModifiers()) || c.isInterface()) {
    throw new IllegalArgumentException("Interceptor must be a concrete class: " + interceptorName);
}
c.getDeclaredConstructor(); // throws NoSuchMethodException if no no-arg ctor
if (!Modifier.isPublic(c.getModifiers())) {
    throw new IllegalArgumentException("Interceptor class must be public: " + interceptorName);
}

Try / catch

try {
    interceptors = BrokerEntryMetadataUtils.loadBrokerEntryMetadataInterceptors(names, conf);
} catch (RuntimeException e) {
    throw new IllegalStateException("Bad BrokerEntryMetadataInterceptor config: check constructor/class", e);
}

Prevention

When it happens

Trigger: brokerEntryMetadataInterceptors config contains a class name whose declared constructor cannot be invoked: class is abstract, has no public no-arg constructor, or the constructor is not accessible.

Common situations: Typos or wrong class configured in broker.conf, custom interceptor class not compiled into the broker, interceptor written with a constructor taking arguments.

Related errors


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