{"record":{"id":"ef525596a7dd305b","repo":"apache/pulsar","slug":"user-class-must-either-be-function-or-java-util-fu","errorCode":null,"errorMessage":"User class must either be Function or java.util.Function","messagePattern":"User class must either be Function or java\\.util\\.Function","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceRunnable.java","lineNumber":265,"sourceCode":"                .attr(\"function\", instanceConfig.getFunctionDetails().getName())\n                .attr(\"details\", instanceConfig.getFunctionDetails())\n                .log(\"Starting Java Instance\");\n\n        Object object;\n        if (instanceConfig.getFunctionDetails().getClassName()\n                .equals(org.apache.pulsar.functions.windowing.WindowFunctionExecutor.class.getName())) {\n            object = Reflections.createInstance(\n                    instanceConfig.getFunctionDetails().getClassName(),\n                    instanceClassLoader);\n        } else {\n            object = Reflections.createInstance(\n                    instanceConfig.getFunctionDetails().getClassName(),\n                    functionClassLoader);\n        }\n\n\n        if (!(object instanceof Function) && !(object instanceof java.util.function.Function)) {\n            throw new RuntimeException(\"User class must either be Function or java.util.Function\");\n        }\n\n        // start the state table\n        setupStateStore();\n\n        ContextImpl contextImpl = setupContext();\n\n        // start the output producer\n        setupOutput(contextImpl);\n        // start the input consumer\n        setupInput(contextImpl);\n        // start any log topic handler\n        setupLogHandler();\n\n        if (!(object instanceof IdentityFunction) && !(sink instanceof PulsarSink)) {\n            sinkSchemaInfoProvider = new SinkSchemaInfoProvider();\n        }\n","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceRunnable.java#L247-L283","documentation":"During JavaInstanceRunnable.setup, the user's class is instantiated and validated: the object must implement org.apache.pulsar.functions.api.Function (or the older WindowFunction path) or java.util.function.Function. If neither interface is implemented, a RuntimeException is thrown because the instance has no callable function interface to invoke. This catches the common mistake of loading a class that isn't actually a function.","triggerScenarios":"Deploying a function whose className points to a class that implements neither pulsar Function nor java.util.function.Function — e.g. a helper class, a class implementing only the deprecated deprecated Function variants, or a wrong class name resolving to a different type in the specified classloader.","commonSituations":"Typo/wrong value in the function's className config; jar containing multiple versions of the class; upgrading code where the function no longer implements the API; using Scala/Groovy lambdas or classes that implement similar but distinct interfaces.","solutions":["Make the user class implement org.apache.pulsar.functions.api.Function<I,O> (or java.util.function.Function) and redeploy.","Verify the function's className setting points at the correct fully-qualified class in the uploaded jar.","Check the function's jar/classloader contains the right version of the class (no stale jars)."],"exampleFix":"// before\npublic class MyProcessor {\n    public String process(String input) { return input.toUpperCase(); }\n}\n// after\npublic class MyProcessor implements Function<String, String> {\n    @Override\n    public String process(String input, Context context) { return input.toUpperCase(); }\n}","handlingStrategy":"validation","validationCode":"Class<?> c = functionClassLoader.loadClass(className);\nif (!org.apache.pulsar.functions.api.Function.class.isAssignableFrom(c)\n    && !java.util.function.Function.class.isAssignableFrom(c)) {\n    throw new IllegalArgumentException(className + \" must implement Function or java.util.function.Function\");\n}","typeGuard":"boolean isUserFunction(Object o) {\n  return o instanceof org.apache.pulsar.functions.api.Function\n      || o instanceof java.util.function.Function;\n}","tryCatchPattern":"try { new JavaInstanceRunnable(...); } catch (RuntimeException e) { if (e.getMessage().startsWith(\"User class must\")) { throw new IllegalStateException(\"Fix function className or implement Function\", e); } throw e; }","preventionTips":["Verify className points to a class implementing Function/java.util.function.Function","Smoke-test the jar locally before deploying the function","Avoid duplicate class versions across function jars","Use pulsar-admin functions create validation output to catch bad classNames early"],"tags":["pulsar-functions","function-api","class-loading","configuration"],"backgroundTag":"class-does-not-implement-interface","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}