apache/pulsar · error · IllegalArgumentException

%s Package is not provided

Error message

%s Package is not provided

What it means

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.

Source

Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java:168

        FunctionDetails functionDetails;
        File componentPackageFile = null;
        try {

            // validate parameters
            try {
                if (isNotBlank(sinkPkgUrl)) {
                    componentPackageFile = getPackageFile(componentType, sinkPkgUrl);
                    functionDetails = validateUpdateRequestParams(tenant, namespace, sinkName,
                            sinkConfig, componentPackageFile);
                } else {
                    if (uploadedInputStream != null) {
                        componentPackageFile = WorkerUtils.dumpToTmpFile(uploadedInputStream);
                    }
                    functionDetails = validateUpdateRequestParams(tenant, namespace, sinkName,
                            sinkConfig, componentPackageFile);
                    if (!isFunctionCodeBuiltin(functionDetails)
                            && (componentPackageFile == null || fileDetail == null)) {
                        throw new IllegalArgumentException(
                                ComponentTypeUtils.toString(componentType) + " Package is not provided");
                    }
                }
            } catch (Exception e) {
                log.error().attr("componentType", ComponentTypeUtils.toString(componentType)).attr("tenant", tenant)

                        .attr("namespace", namespace).attr("componentName", sinkName).exception(e)

                        .log("Invalid register request @ / / /");
                throw new RestException(Response.Status.BAD_REQUEST, e.getMessage());
            }

            try {
                worker().getFunctionRuntimeManager().getRuntimeFactory().doAdmissionChecks(functionDetails);
            } catch (Exception e) {
                log.error().attr("componentType", ComponentTypeUtils.toString(componentType)).attr("tenant", tenant)

                        .attr("namespace", namespace).attr("componentName", sinkName)

View on GitHub (pinned to 820761864e)

Solutions

  1. Provide the sink archive: attach the NAR/JAR file in the multipart upload or set sinkPkgUrl to a valid http/file package URL.
  2. If using a bundled connector, set sinkConfig.builtin (and archive) to the builtin sink name so isFunctionCodeBuiltin passes.
  3. Verify the multipart part carrying the file is named correctly so fileDetail is non-null server-side.
  4. Check worker logs ('Invalid register request') to confirm which validation failed.

Example fix

// before: no package and no builtin
POST /admin/v3/sinks/my-tenant/my-ns/my-sink  (no file part, sinkConfig.className="com.me.MySink")
// after: upload the archive
POST /admin/v3/sinks/my-tenant/my-ns/my-sink -F "url=@my-sink.nar" -F "sinkConfig={...};type=application/json"
// or use a builtin connector
sinkConfig.setBuiltin("elastic-search");
Defensive patterns

Strategy: validation

Validate before calling

boolean canRegister = cfg.getBuiltin() != null || pkgUrl != null || archiveFile != null;
if (!canRegister) throw new IllegalStateException("Provide a builtin connector or an archive (file/pkgUrl)");

Try / catch

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; }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/63ffdaf1bffcfd47. Report an issue: GitHub.