apache/pulsar · error · RuntimeException

User class doesn't have such method

Error message

User class doesn't have such method

What it means

getTimeStampExtractor obtains the extractor's declared no-arg constructor via theCls.getDeclaredConstructor(). If no such constructor exists, NoSuchMethodException is rethrown as "User class doesn't have such method". The timestamp extractor must expose a no-arg constructor for reflective instantiation by the executor.

Source

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

        Class<?> theCls;
        try {
            theCls = Class.forName(windowConfig.getTimestampExtractorClassName(),
                    true, Thread.currentThread().getContextClassLoader());
        } 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,

View on GitHub (pinned to 820761864e)

Solutions

  1. Add a public no-arg constructor to the timestamp extractor class
  2. If initialization data is needed, use a settable field or static config lookup instead of constructor args
  3. Rebuild/redeploy and verify the class in the jar actually has the constructor (javap -p)

Example fix

// before
public class MyExtractor implements TimestampExtractor<String> {
    public MyExtractor(String topic) { ... }
}
// after
public class MyExtractor implements TimestampExtractor<String> {
    public MyExtractor() { }
    public MyExtractor(String topic) { ... }
    public long extractTimestamp(String record) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

try {
    Class.forName(className).getDeclaredConstructor();
} catch (NoSuchMethodException e) {
    throw new IllegalStateException("extractor lacks a no-arg constructor: " + className);
}

Try / catch

try {
    executor.initialize();
} catch (RuntimeException e) {
    if ("User class doesn't have such method".equals(e.getMessage())) {
        throw new IllegalStateException("add a public no-arg constructor to the extractor", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Configured extractor class only defines parameterized constructors; getDeclaredConstructor() with no argument list fails during getWindowManager initialization.

Common situations: Constructor requiring config/dependencies injected; code generated with required args; Lombok/records without an explicit no-arg constructor.

Related errors


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