{"record":{"id":"8771ec6179198ab4","repo":"apache/pulsar","slug":"function-class-s-does-not-implement-the-correct-i","errorCode":null,"errorMessage":"Function class %s does not implement the correct interface","messagePattern":"Function class (.+?) does not implement the correct interface","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java","lineNumber":650,"sourceCode":"            // thus we should try to find its class name in the NAR service definition\n            if (functionClassName == null) {\n                FunctionDefinition functionDefinition =\n                        validatableFunctionPackage.getFunctionMetaData(FunctionDefinition.class);\n                if (functionDefinition == null) {\n                    throw new IllegalArgumentException(\"Function class name is not provided.\");\n                }\n                functionClassName = functionDefinition.getFunctionClass();\n                if (functionClassName == null) {\n                    throw new IllegalArgumentException(\"Function class name is not provided.\");\n                }\n            }\n            functionClass = validatableFunctionPackage.resolveType(functionClassName);\n\n            if (!functionClass.asErasure().isAssignableTo(org.apache.pulsar.functions.api.Function.class)\n                    && !functionClass.asErasure().isAssignableTo(java.util.function.Function.class)\n                    && !functionClass.asErasure()\n                    .isAssignableTo(org.apache.pulsar.functions.api.WindowFunction.class)) {\n                throw new IllegalArgumentException(\n                        String.format(\"Function class %s does not implement the correct interface\",\n                                functionClassName));\n            }\n        } catch (TypePool.Resolution.NoSuchTypeException e) {\n            throw new IllegalArgumentException(\n                    String.format(\"Function class %s must be in class path\", functionClassName), e);\n        }\n\n        TypeDefinition[] typeArgs = FunctionCommon.getFunctionTypes(functionConfig, functionClass);\n        // inputs use default schema, so there is no check needed there\n\n        // Check if the Input serialization/deserialization class exists in jar or already loaded and that it\n        // implements SerDe class\n        if (functionConfig.getCustomSerdeInputs() != null) {\n            functionConfig.getCustomSerdeInputs().forEach((topicName, inputSerializer) -> {\n                ValidatorUtils.validateSerde(inputSerializer, typeArgs[0], validatableFunctionPackage.getTypePool(),\n                        true);\n            });","sourceCodeStart":632,"sourceCodeEnd":668,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java#L632-L668","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\npublic class MyProcessor { public String process(String in) { return in; } }\n// after\npublic class MyProcessor implements org.apache.pulsar.functions.api.Function<String, String> {\n    public String apply(String in) { return in; }\n}","handlingStrategy":"validation","validationCode":"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\"); }","typeGuard":"boolean isSupportedFunction(Class<?> c) { return Function.class.isAssignableFrom(c) || java.util.function.Function.class.isAssignableFrom(c) || WindowFunction.class.isAssignableFrom(c); }","tryCatchPattern":"try { ... } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"correct interface\")) { log.error(\"Fix implements clause on {}\", config.getClassName()); } }","preventionTips":["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"],"tags":["pulsar","functions","java","type-check"],"backgroundTag":"function-interface-not-implemented","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}