apache/pulsar · error · RuntimeException
Timestamp extractor class %s must be in class path
Error message
Timestamp extractor class %s must be in class path
What it means
When a custom timestampExtractorClassName is configured, getTimeStampExtractor loads it with Class.forName using the thread context classloader. If the class (or something it references) cannot be found or linked, the executor wraps the ClassNotFoundException/NoClassDefFoundError in a RuntimeException naming the class. This means the user's timestamp extractor jar is not shipped with the function or the class name is wrong.
Source
Thrown at pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/windowing/WindowFunctionExecutor.java:137
EvictionPolicy<Record<T>, ?> evictionPolicy = getEvictionPolicy(windowConfig);
TriggerPolicy<Record<T>, ?> triggerPolicy = getTriggerPolicy(windowConfig, manager,
evictionPolicy, context);
manager.setEvictionPolicy(evictionPolicy);
manager.setTriggerPolicy(triggerPolicy);
return manager;
}
@SuppressWarnings("unchecked")
private TimestampExtractor<T> getTimeStampExtractor(WindowConfig windowConfig) {
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);
}View on GitHub (pinned to 820761864e)
Solutions
- Bundle the timestamp extractor class (and its dependencies) in the function jar and redeploy
- Correct the fully-qualified class name in WindowConfig.timestampExtractorClassName
- Check function instance logs for the caused-by ClassNotFoundException to see the missing class name
- Ensure the class is on the function instance classpath, not only the broker's
Example fix
// before "timestampExtractorClassName": "com.example.TimeStampExtractor" // typo, class not uploaded // after "timestampExtractorClassName": "com.example.MyTimestampExtractor" // included in function uber-jar
Defensive patterns
Strategy: validation
Validate before calling
try {
Class.forName(className, true, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException("extractor class not in function jar: " + className);
} Try / catch
try {
executor.initialize();
} catch (RuntimeException e) {
if (e.getCause() instanceof ClassNotFoundException || e.getCause() instanceof NoClassDefFoundError) {
throw new IllegalStateException("bundle the extractor class and its dependencies in the function jar", e);
}
throw e;
} Prevention
- Build the function as an uber-jar containing the extractor and its transitive deps
- Verify the fully-qualified class name with `jar tf app.jar | grep TimestampExtractor`
- Test extractor loading locally with the same classloader setup
When it happens
Trigger: WindowConfig.timestampExtractorClassName set to a class not in the function's fat jar / nar; typo in fully-qualified name; NoClassDefFoundError from a missing transitive dependency of the extractor.
Common situations: Deploying a function without uploading the extractor class's jar; package rename after refactor; class present in broker but not in function instance classpath.
Related errors
- Config class not found: %s
- Window function must take a collection as input
- Window function does not implement the correct interface
- Window Configs cannot be found
- Late data topic can be defined only when specifying a timest
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/500eca86323cbd4c.
Report an issue: GitHub.