apache/pulsar · error · IllegalArgumentException
Function class %s does not implement the correct interface
Error message
Function class %s does not implement the correct interface
What it means
doJavaChecks resolves the configured class in the function package and verifies it implements one of the supported interfaces: org.apache.pulsar.functions.api.Function, java.util.function.Function, or WindowFunction. If the resolved type implements none of them, IllegalArgumentException is thrown.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:650
// thus we should try to find its class name in the NAR service definition
if (functionClassName == null) {
FunctionDefinition functionDefinition =
validatableFunctionPackage.getFunctionMetaData(FunctionDefinition.class);
if (functionDefinition == null) {
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);
});View on GitHub (pinned to 820761864e)
Solutions
- Make the configured class implement org.apache.pulsar.functions.api.Function (or WindowFunction / java.util.function.Function)
- Correct the className so it points to the actual function class
- Ensure the interface is from the same Pulsar client API version as the validator
Example fix
// before
public class MyProcessor { public String process(String in) { return in; } }
// after
public class MyProcessor implements org.apache.pulsar.functions.api.Function<String, String> {
public String apply(String in) { return in; }
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = Class.forName(config.getClassName(), false, loader); if (!Function.class.isAssignableFrom(c) && !java.util.function.Function.class.isAssignableFrom(c) && !WindowFunction.class.isAssignableFrom(c)) { throw new IllegalArgumentException(config.getClassName() + " must implement a supported function interface"); } Type guard
boolean isSupportedFunction(Class<?> c) { return Function.class.isAssignableFrom(c) || java.util.function.Function.class.isAssignableFrom(c) || WindowFunction.class.isAssignableFrom(c); } Try / catch
try { ... } catch (IllegalArgumentException e) { if (e.getMessage().contains("correct interface")) { log.error("Fix implements clause on {}", config.getClassName()); } } Prevention
- Implement org.apache.pulsar.functions.api.Function for new functions
- Point className at the concrete function class, not helpers
- Keep the Pulsar functions API dependency version aligned with the cluster
When it happens
Trigger: FunctionConfig.className points to a class that does not implement any supported function interface, e.g. a plain class or a class implementing only a different framework's interface.
Common situations: Typo in the class name resolving to the wrong type; refactoring removed the implements clause; pointing the config at a helper class instead of the actual function class.
Related errors
- Function class name is not provided.
- Function class %s must be in class path
- Failed to compute configuration overrides
- Invalid short topic name '${completeTopicName}', it should b
- V1 topic names (with cluster component) are no longer suppor
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/8771ec6179198ab4.
Report an issue: GitHub.