apache/pulsar · error · RuntimeException
Class must be in class path
Error message
Class must be in class path
What it means
JavaInstanceMain.createInstance() loads the user function class with Class.forName(userClassName, true, classLoader) on the function instance classloader. If the class (or a type it references during linking) cannot be found, ClassNotFoundException/NoClassDefFoundError is wrapped into RuntimeException("Class X must be in class path").
Source
Thrown at pulsar-functions/runtime-all/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceMain.java:137
method.invoke(main, args, functionInstanceClsLoader, root);
} catch (Throwable e) {
try {
shutdownLogging();
} finally {
System.out.println("Failed to start function instance.");
e.printStackTrace();
Runtime.getRuntime().halt(1);
}
}
}
public static Object createInstance(String userClassName,
ClassLoader classLoader) {
Class<?> theCls;
try {
theCls = Class.forName(userClassName, true, classLoader);
} catch (ClassNotFoundException | NoClassDefFoundError cnfe) {
throw new RuntimeException("Class " + userClassName + " must be in class path", cnfe);
}
Object result;
try {
Constructor<?> meth = theCls.getDeclaredConstructor();
meth.setAccessible(true);
result = meth.newInstance();
} catch (InstantiationException ie) {
throw new RuntimeException("User class must be concrete", ie);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Class " + userClassName + " doesn't have such method", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Class " + userClassName + " must have a no-arg constructor", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Class " + userClassName + " constructor throws exception", e);
}
return result;
}View on GitHub (pinned to 820761864e)
Solutions
- Verify the fully qualified class name in the function config matches an actual class in the submitted jar (check with `jar tf app.jar | grep MyFunction`).
- Rebuild/re-submit the function jar ensuring the class and its dependencies are packaged (shade or bundle deps).
- Confirm the jar URL(s) passed to loadJar include the user jar file.
- Check for NoClassDefFoundError cause — a missing dependency class, not just the function class itself.
Example fix
// before (stale name after refactor) --className com.example.OldFunctionName // after --className com.example.MyFunction
Defensive patterns
Strategy: validation
Validate before calling
// verify before submitting the function
Process p = new ProcessBuilder("jar", "tf", "app.jar").start();
// or in-process:
boolean found = java.util.Collections.list(loader.getResources("com/example/MyFunction.class")).size() > 0; Type guard
boolean classLoadable(ClassLoader cl, String fcn) { try { Class.forName(fcn, false, cl); return true; } catch (Throwable t) { return false; } } Try / catch
try { Object f = JavaInstanceMain.createInstance(className, cl); } catch (RuntimeException e) { if (e.getCause() instanceof NoClassDefFoundError) { /* missing dependency, not just the class */ } throw e; } Prevention
- Validate the className exists in the jar at submission time (broker-side validation or CI check).
- Shade/bundle all dependencies into the function jar.
- Grep the jar (`jar tf`) for the exact FQCN before deploying.
- Avoid renaming packages without re-submitting updated function configs.
When it happens
Trigger: The function's user jar was not added to the classloader passed to createInstance (jars from loadJar missing), or the configured className is wrong/renamed, or the class references a dependency that is not on the provided classpath.
Common situations: Typos or stale FQCN in the function config after refactoring; submitting a function whose jar doesn't contain the class; shaded jar that excluded a needed dependency; package rename between versions.
Related errors
- (wraps ClassNotFoundException for BrokerEntryMetadataInterce
- (wraps ClassNotFoundException for interceptor)
- User class must be in class path
- Failed to load an authorization provider.
- Failed to instantiate ${className}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/824a105a53cb5714.
Report an issue: GitHub.