apache/pulsar · error · RuntimeException

User class constructor throws exception

Error message

User class constructor throws exception

What it means

If the extractor's no-arg constructor itself throws during newInstance(), the InvocationTargetException is rethrown as "User class constructor throws exception", with the original cause chained. This means the extractor class was found, concrete, and accessible, but its own initialization code failed at runtime. Inspect the chained cause for the real failure.

Source

Thrown at pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/windowing/WindowFunctionExecutor.java:154

        } catch (ClassNotFoundException | NoClassDefFoundError cnfe) {
            throw new RuntimeException(
                    String.format("Timestamp extractor class %s must be in class path",
                            windowConfig.getTimestampExtractorClassName()), cnfe);
        }

        Object result;
        try {
            Constructor<?> constructor = theCls.getDeclaredConstructor();
            constructor.setAccessible(true);
            result = constructor.newInstance();
        } catch (InstantiationException ie) {
            throw new RuntimeException("User class must be concrete", ie);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException("User class doesn't have such method", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("User class must have a no-arg constructor", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("User class constructor throws exception", e);
        }
        Class<?>[] timestampExtractorTypeArgs = TypeResolver.resolveRawArguments(
                TimestampExtractor.class, result.getClass());
        Class<?>[] typeArgs = TypeResolver.resolveRawArguments(Function.class, this.getClass());
        if (!typeArgs[0].equals(timestampExtractorTypeArgs[0])) {
            throw new RuntimeException(
                    "Inconsistent types found between function input type and timestamp extractor type: "
                            + " function type = " + typeArgs[0] + ", timestamp extractor type = "
                            + timestampExtractorTypeArgs[0]);
        }
        return (TimestampExtractor<T>) result;
    }

    private TriggerPolicy<Record<T>, ?> getTriggerPolicy(WindowConfig windowConfig, WindowManager<Record<T>> manager,
                                                         EvictionPolicy<Record<T>, ?> evictionPolicy, Context context) {
        if (windowConfig.getSlidingIntervalCount() != null) {
            if (this.isEventTime()) {
                return new WatermarkCountTriggerPolicy<>(

View on GitHub (pinned to 820761864e)

Solutions

  1. Read the caused-by of this exception in the function logs to find the constructor's real failure
  2. Move heavy/failing initialization out of the constructor into lazy first use or open()/close lifecycle hooks
  3. Harden the constructor against missing config (defaults, null checks)
  4. Rebuild/redeploy and re-test with the environment the function instance actually runs in

Example fix

// before
public MyExtractor() {
    this.settings = Files.readAllBytes(Paths.get("/etc/extractor.conf")); // throws in function runtime
}
// after
public MyExtractor() {
    this.settings = loadOrDefault("/etc/extractor.conf");
}
private static byte[] loadOrDefault(String p) {
    try { return Files.readAllBytes(Paths.get(p)); } catch (Exception e) { return new byte[0]; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the constructor runs cleanly in the same environment as the function
try {
    Class.forName(className).getDeclaredConstructor().newInstance();
} catch (InvocationTargetException e) {
    throw new IllegalStateException("extractor ctor throws: " + e.getTargetException(), e);
}

Try / catch

try {
    executor.initialize();
} catch (RuntimeException e) {
    if ("User class constructor throws exception".equals(e.getMessage()) && e.getCause() != null) {
        // e.getCause() is the real exception thrown by the extractor constructor
        throw new IllegalStateException("extractor init failed: " + e.getCause().getMessage(), e.getCause());
    }
    throw e;
}

Prevention

When it happens

Trigger: Constructor performs I/O, loads config/resources, connects to a service, or dereferences null and throws; reflective invocation wraps it in InvocationTargetException during initialize/getWindowManager.

Common situations: Constructor reading a missing config file or env var; static initializers failing; environment-specific setup (paths, credentials) not available inside the function instance.

Related errors


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