apache/pulsar · error · IllegalArgumentException

%s Package is not provided

Error message

%s Package is not provided

What it means

When registering a function whose code is not a built-in archive, the request must carry the component package (uploaded jar/zip via the file upload field). If isFunctionCodeBuiltin is false but componentPackageFile or the uploaded file detail is null, registerFunction throws IllegalArgumentException '<ComponentType> Package is not provided' (surfaced as HTTP 400). Built-in (builtin://) packages are exempt.

Source

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

        FunctionDetails functionDetails;
        File componentPackageFile = null;
        try {

            // validate parameters
            try {
                if (isNotBlank(functionPkgUrl)) {
                    componentPackageFile = getPackageFile(componentType, functionPkgUrl);
                    functionDetails = validateUpdateRequestParams(tenant, namespace, functionName,
                            functionConfig, componentPackageFile);
                } else {
                    if (uploadedInputStream != null) {
                        componentPackageFile = WorkerUtils.dumpToTmpFile(uploadedInputStream);
                    }
                    functionDetails = validateUpdateRequestParams(tenant, namespace, functionName,
                            functionConfig, 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", functionName).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", functionName).exception(e)

View on GitHub (pinned to 820761864e)

Solutions

  1. Attach the package file: 'pulsar-admin functions create --jar /path/to/function.jar ...'
  2. For REST, include the jar as the multipart upload (data field) alongside the functionConfig
  3. Alternatively use 'builtin://<name>' for a valid installed built-in archive so no upload is required

Example fix

// before
pulsar-admin functions create --tenant public --namespace default --name fn --classname org.foo.Fn
// after
pulsar-admin functions create --tenant public --namespace default --name fn --classname org.foo.Fn --jar /path/to/function.jar
Defensive patterns

Strategy: validation

Validate before calling

boolean builtin = cfg.getArchive() != null && cfg.getArchive().startsWith("builtin://");
java.io.File jar = new java.io.File(jarPath);
if (!builtin && !(jar.exists() && jar.length() > 0)) {
    throw new IllegalArgumentException("--jar package required for non-builtin functions");
}

Type guard

boolean packageProvided(FunctionConfig cfg, java.io.File jar) {
    boolean builtin = cfg != null && cfg.getArchive() != null && cfg.getArchive().startsWith("builtin://");
    return builtin || (jar != null && jar.isFile() && jar.length() > 0);
}

Try / catch

try { admin.functions().createFunction(tenant, ns, name, pkgUrl, cfg, jarPath); }
catch (PulsarAdminException e) {
    if (e.getStatusCode() == 400 && String.valueOf(e.getMessage()).contains("Package is not provided")) {
        // attach the jar upload and retry
    }
}

Prevention

When it happens

Trigger: Registering with a normal (non-builtin) code URL but omitting the multipart file upload / --jar file; sending functionConfig without the package input stream.

Common situations: CLI invocation missing --jar; REST call without the multipart 'data' part; using builtin:// incorrectly removed while no file uploaded; scripts passing a URL as if the worker could fetch it when this API requires the upload.

Related errors


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