apache/pulsar · error · IllegalArgumentException
Function class %s must be in class path
Error message
Function class %s must be in class path
What it means
While resolving the configured function class via the NAR package TypePool, the type could not be found, so doJavaChecks throws IllegalArgumentException with the cause NoSuchTypeException. The class name resolved syntactically but the bytecode is not present in the function package.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:655
throw new IllegalArgumentException("Function class name is not provided.");
}
functionClassName = functionDefinition.getFunctionClass();
if (functionClassName == null) {
throw new IllegalArgumentException("Function class name is not provided.");
}
}
functionClass = validatableFunctionPackage.resolveType(functionClassName);
if (!functionClass.asErasure().isAssignableTo(org.apache.pulsar.functions.api.Function.class)
&& !functionClass.asErasure().isAssignableTo(java.util.function.Function.class)
&& !functionClass.asErasure()
.isAssignableTo(org.apache.pulsar.functions.api.WindowFunction.class)) {
throw new IllegalArgumentException(
String.format("Function class %s does not implement the correct interface",
functionClassName));
}
} catch (TypePool.Resolution.NoSuchTypeException e) {
throw new IllegalArgumentException(
String.format("Function class %s must be in class path", functionClassName), e);
}
TypeDefinition[] typeArgs = FunctionCommon.getFunctionTypes(functionConfig, functionClass);
// inputs use default schema, so there is no check needed there
// Check if the Input serialization/deserialization class exists in jar or already loaded and that it
// implements SerDe class
if (functionConfig.getCustomSerdeInputs() != null) {
functionConfig.getCustomSerdeInputs().forEach((topicName, inputSerializer) -> {
ValidatorUtils.validateSerde(inputSerializer, typeArgs[0], validatableFunctionPackage.getTypePool(),
true);
});
}
// Check if the Input serialization/deserialization class exists in jar or already loaded and that it
// implements SerDe class
if (functionConfig.getCustomSchemaInputs() != null) {View on GitHub (pinned to 820761864e)
Solutions
- Ensure the class named in className exists in the submitted archive (check jar tf / unzip -l)
- Correct any typo in the fully qualified class name
- Rebuild the fat/NAR package so the function class and its dependencies are bundled
Example fix
// before
config.setClassName("org.example.MyFuntion"); // typo, class not in jar
// after
config.setClassName("org.example.MyFunction"); // present in the submitted jar Defensive patterns
Strategy: validation
Validate before calling
try (JarFile jar = new JarFile(archivePath)) { if (jar.getJarEntry(config.getClassName().replace('.', '/') + ".class") == null) { throw new IllegalArgumentException("Class " + config.getClassName() + " not present in archive"); } } Type guard
boolean classInArchive(String archive, String fqcn) throws IOException { try (JarFile jf = new JarFile(archive)) { return jf.getJarEntry(fqcn.replace('.', '/') + ".class") != null; } } Try / catch
try { ... } catch (IllegalArgumentException e) { Throwable cause = e.getCause(); if (cause instanceof TypePool.Resolution.NoSuchTypeException) { log.error("Bundle the missing class into the function archive"); } } Prevention
- Run 'jar tf' to confirm the class exists before submitting
- Ensure shading config keeps the function class un-renamed
- Submit the actual function fat JAR/NAR, not a dependency-only JAR
When it happens
Trigger: className references a class that is not contained in the submitted JAR/NAR (resolution by TypePool fails), including classes whose dependencies were not bundled.
Common situations: Shading/proguard stripped or renamed the class; fat JAR missing the function class; class name typo that still resolves as a valid binary name; dependency-only JAR submitted instead of the function JAR.
Related errors
- Function class name is not provided.
- Function class %s does not implement the correct interface
- Could not find sink config class
- Entry filter `${name}` cannot be loaded, see the broker logs
- Failed to load an authorization provider.
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/36748f0d1ab15a8b.
Report an issue: GitHub.