{"record":{"id":"dbda88549d8481a8","repo":"apache/pulsar","slug":"either-a-java-jar-or-a-python-file-or-a-go-executa","errorCode":null,"errorMessage":"Either a Java jar or a Python file or a Go executable binary needs to be specified for the function. Cannot specify both.","messagePattern":"Either a Java jar or a Python file or a Go executable binary needs to be specified for the function\\. Cannot specify both\\.","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java","lineNumber":719,"sourceCode":"                    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\"\n                        + \" be specified for the function. Cannot specify both.\");\n            }\n\n            if (isBlank(functionConfig.getJar()) && isBlank(functionConfig.getPy())\n                    && isBlank(functionConfig.getGo())) {\n                throw new ParameterException(\"Either a Java jar or a Python file or a Go executable binary needs to\"\n                        + \" be specified for the function. Please specify one.\");\n            }\n\n            if (!isBlank(functionConfig.getJar()) && !functionConfig.getJar().startsWith(\"builtin://\")\n                    && !Utils.isFunctionPackageUrlSupported(functionConfig.getJar())\n                    && !new File(functionConfig.getJar()).exists()) {\n                throw new ParameterException(\"The specified jar file does not exist\");\n            }\n            if (!isBlank(functionConfig.getPy()) && !Utils.isFunctionPackageUrlSupported(functionConfig.getPy())\n                    && !new File(functionConfig.getPy()).exists()) {\n                throw new ParameterException(\"The specified python file does not exist\");\n            }","sourceCodeStart":701,"sourceCodeEnd":737,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java#L701-L737","documentation":"This ParameterException is thrown by the pulsar-admin CLI when validating a FunctionConfig before creating/updating a Pulsar Function. The functions API requires exactly one code artifact: a Java jar, a Python file, or a Go executable binary. The check is meant to reject mutually exclusive specification, but due to a logic bug the condition uses `isBlank(getJar()) && isBlank(getPy()) && isBlank(getGo())` style combined incorrectly — in practice this branch fires when more than one artifact (specifically when jar, py and go fields conflict per the source condition) is set, which is ambiguous. It signals that the user tried to specify multiple artifact types at once.","triggerScenarios":"Running `pulsar-admin functions create/update` (or localrun) with a FunctionConfig where multiple artifact fields are set — e.g. both --jar and --py (or --go) are non-blank — reaching FunctionDetailsCommand.validateFunctionConfigs at CmdFunctions.java:719.","commonSituations":"Copying an old function config and adding a new artifact type; scripted deployments that set defaults for --jar while also passing --py; migrating a function from Java to Python without removing the jar field; YAML/JSON function configs left with stale artifact entries.","solutions":["Remove all but one of --jar/--py/--go from the command or FunctionConfig so exactly one artifact is specified","If migrating languages, delete the stale artifact field from your function config YAML/JSON","Fix scripts/templates so only the intended artifact option is populated"],"exampleFix":"// before\npulsar-admin functions create --tenant t --namespace n --name f --jar my.jar --py func.py\n// after\npulsar-admin functions create --tenant t --namespace n --name f --py func.py","handlingStrategy":"validation","validationCode":"String jar = functionConfig.getJar(), py = functionConfig.getPy(), go = functionConfig.getGo();\nint set = (jar != null && !jar.isBlank() ? 1 : 0) + (py != null && !py.isBlank() ? 1 : 0)\n        + (go != null && !go.isBlank() ? 1 : 0);\nif (set != 1) throw new IllegalArgumentException(\"Specify exactly one of --jar, --py, --go\");","typeGuard":"boolean hasExactlyOneArtifact(FunctionConfig c) {\n    int n = (isNonBlank(c.getJar()) ? 1 : 0) + (isNonBlank(c.getPy()) ? 1 : 0) + (isNonBlank(c.getGo()) ? 1 : 0);\n    return n == 1;\n}","tryCatchPattern":"try { admin.functions().createFunction(...); }\ncatch (ParameterException e) { if (e.getMessage().contains(\"Cannot specify both\")) { /* strip extra artifact fields and retry */ } else throw e; }","preventionTips":["Templated function configs should define only one artifact field","Lint CI configs for functions to ensure exactly one of jar/py/go is set","When migrating a function between languages, delete the old artifact field"],"tags":["cli","validation","pulsar-functions"],"backgroundTag":"mutually-exclusive-options","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"}