{"record":{"id":"63ffdaf1bffcfd47","repo":"apache/pulsar","slug":"s-package-is-not-provided-63ffda","errorCode":null,"errorMessage":"%s Package is not provided","messagePattern":"(.+?) Package is not provided","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java","lineNumber":168,"sourceCode":"        FunctionDetails functionDetails;\n        File componentPackageFile = null;\n        try {\n\n            // validate parameters\n            try {\n                if (isNotBlank(sinkPkgUrl)) {\n                    componentPackageFile = getPackageFile(componentType, sinkPkgUrl);\n                    functionDetails = validateUpdateRequestParams(tenant, namespace, sinkName,\n                            sinkConfig, componentPackageFile);\n                } else {\n                    if (uploadedInputStream != null) {\n                        componentPackageFile = WorkerUtils.dumpToTmpFile(uploadedInputStream);\n                    }\n                    functionDetails = validateUpdateRequestParams(tenant, namespace, sinkName,\n                            sinkConfig, componentPackageFile);\n                    if (!isFunctionCodeBuiltin(functionDetails)\n                            && (componentPackageFile == null || fileDetail == null)) {\n                        throw new IllegalArgumentException(\n                                ComponentTypeUtils.toString(componentType) + \" Package is not provided\");\n                    }\n                }\n            } catch (Exception e) {\n                log.error().attr(\"componentType\", ComponentTypeUtils.toString(componentType)).attr(\"tenant\", tenant)\n\n                        .attr(\"namespace\", namespace).attr(\"componentName\", sinkName).exception(e)\n\n                        .log(\"Invalid register request @ / / /\");\n                throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());\n            }\n\n            try {\n                worker().getFunctionRuntimeManager().getRuntimeFactory().doAdmissionChecks(functionDetails);\n            } catch (Exception e) {\n                log.error().attr(\"componentType\", ComponentTypeUtils.toString(componentType)).attr(\"tenant\", tenant)\n\n                        .attr(\"namespace\", namespace).attr(\"componentName\", sinkName)","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java#L150-L186","documentation":"During sink registration via registerSink, when no package URL (sinkPkgUrl) is supplied, the worker validates that the sink's code is available somewhere: either marked as builtin in the sink config or supplied as an uploaded package (file + input stream). If the FunctionDetails are not builtin and no package file/upload was received, the worker throws IllegalArgumentException('Sink Package is not provided'), which is converted to HTTP 400.","triggerScenarios":"Calling POST /admin/v3/sinks/{tenant}/{namespace}/{sinkName} without sinkPkgUrl, without an uploaded jar file body, and with a sinkConfig whose className is not a builtin connector (archive/builtin field not set to a known builtin sink).","commonSituations":"Client SDK calls that omit the file upload part while intending a custom sink; forgetting to set 'builtin' in SinkConfig when using a bundled connector; multipart form where fileDetail is null because the jar part name is wrong; tools that pass packageName instead of the actual archive.","solutions":["Provide the sink archive: attach the NAR/JAR file in the multipart upload or set sinkPkgUrl to a valid http/file package URL.","If using a bundled connector, set sinkConfig.builtin (and archive) to the builtin sink name so isFunctionCodeBuiltin passes.","Verify the multipart part carrying the file is named correctly so fileDetail is non-null server-side.","Check worker logs ('Invalid register request') to confirm which validation failed."],"exampleFix":"// before: no package and no builtin\nPOST /admin/v3/sinks/my-tenant/my-ns/my-sink  (no file part, sinkConfig.className=\"com.me.MySink\")\n// after: upload the archive\nPOST /admin/v3/sinks/my-tenant/my-ns/my-sink -F \"url=@my-sink.nar\" -F \"sinkConfig={...};type=application/json\"\n// or use a builtin connector\nsinkConfig.setBuiltin(\"elastic-search\");","handlingStrategy":"validation","validationCode":"boolean canRegister = cfg.getBuiltin() != null || pkgUrl != null || archiveFile != null;\nif (!canRegister) throw new IllegalStateException(\"Provide a builtin connector or an archive (file/pkgUrl)\");","typeGuard":null,"tryCatchPattern":"try { admin.sinks().createSink(cfg, archive); } catch (PulsarAdminException e) { if (e.getStatusCode() == 400 && String.valueOf(e.getMessage()).contains(\"Package is not provided\")) { /* attach archive and retry */ } else throw e; }","preventionTips":["Always attach the NAR/JAR or set sinkPkgUrl when className is not builtin","Set sinkConfig.builtin for connectors bundled with the worker","Check the multipart file part name matches what the REST endpoint expects","Dry-run config validation in CI before hitting the admin API"],"tags":["rest-api","validation","pulsar-functions","sink","bad-request"],"backgroundTag":"missing-package-artifact","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"}