{"record":{"id":"78e31201780eadd3","repo":"apache/pulsar","slug":"no-function-classname-specified","errorCode":null,"errorMessage":"No Function Classname specified","messagePattern":"No Function Classname specified","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java","lineNumber":701,"sourceCode":"                userCodeFile = functionConfig.getPy();\n            } else if (functionConfig.getGo() != null) {\n                userCodeFile = functionConfig.getGo();\n            }\n\n            if (null != runtimeFlags) {\n                functionConfig.setRuntimeFlags(runtimeFlags);\n            }\n\n            // check if configs are valid\n            validateFunctionConfigs(functionConfig);\n        }\n\n        protected void validateFunctionConfigs(FunctionConfig functionConfig) {\n            // go doesn't need className\n            if (functionConfig.getPy() != null\n                    || (functionConfig.getJar() != null && !functionConfig.getJar().startsWith(\"builtin://\"))) {\n                if (StringUtils.isEmpty(functionConfig.getClassName())) {\n                    throw new ParameterException(\"No Function Classname specified\");\n                }\n            }\n            if (StringUtils.isEmpty(functionConfig.getName())) {\n                org.apache.pulsar.common.functions.Utils.inferMissingFunctionName(functionConfig);\n            }\n            if (StringUtils.isEmpty(functionConfig.getName())) {\n                throw new IllegalArgumentException(\"No Function name specified\");\n            }\n            if (StringUtils.isEmpty(functionConfig.getTenant())) {\n                org.apache.pulsar.common.functions.Utils.inferMissingTenant(functionConfig);\n            }\n            if (StringUtils.isEmpty(functionConfig.getNamespace())) {\n                org.apache.pulsar.common.functions.Utils.inferMissingNamespace(functionConfig);\n            }\n\n            if (isNotBlank(functionConfig.getJar()) && isNotBlank(functionConfig.getPy())\n                    && isNotBlank(functionConfig.getGo())) {\n                throw new ParameterException(\"Either a Java jar or a Python file or a Go executable binary needs to\"","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java#L683-L719","documentation":"validateFunctionConfigs requires a className for Java/Python functions: it is needed whenever a py config is set, or a jar is set that is not a built-in ('builtin://') reference — Go functions don't need a class name. If className is empty in those cases, a ParameterException 'No Function Classname specified' is thrown.","triggerScenarios":"Functions create/update with a --jar pointing to a local/non-builtin jar and no --classname, or a --py file without a class name; built-in jars (builtin://) and Go functions are exempt.","commonSituations":"Deploying built-in connectors but pointing at a real jar path, forgetting --classname because the jar has one entry, or deploying Go functions while still passing a jar argument that triggers the check.","solutions":["Add --classname with the fully qualified class implementing the function, e.g. --classname org.example.MyFunction.","If using a built-in function, reference the jar as builtin://<type> and pass --function-type so className is not required.","For Go functions use --go instead of --jar so the className check is skipped."],"exampleFix":"// before\npulsar-admin functions create --name ex --jar my.jar\n// after\npulsar-admin functions create --name ex --jar my.jar --classname org.example.MyFunction","handlingStrategy":"validation","validationCode":"boolean needsClassName = pyFile != null || (jarFile != null && !jarFile.startsWith(\"builtin://\"));\nif (needsClassName && StringUtils.isEmpty(className)) {\n    throw new IllegalArgumentException(\"--classname is required with a jar/py function\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    functionsCmd.run();\n} catch (ParameterException e) {\n    if (e.getMessage().contains(\"Classname\")) {\n        System.err.println(\"Add --classname <fqcn> (not needed for builtin:// jars or Go functions).\");\n    }\n}","preventionTips":["Always include --classname when deploying Java jars or Python files.","Use builtin:// references with --function-type for built-ins so className is not required.","Use --go for Go functions instead of --jar."],"tags":["cli","functions","missing-argument","validation"],"backgroundTag":"missing-required-argument","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"}