apache/pulsar · error · IllegalArgumentException

package does not have the correct format. Pulsar cannot…

Error message

%s package does not have the correct format. Pulsar cannot determine if the package is a NAR package or JAR package. %s classname is not provided and attempts to load it as a NAR package produced the following error.

What it means

getClassLoaderFromPackage first tries loading the archive as a NAR, then (if a connector class name is given) as a JAR. When no connector class name is provided and the NAR attempt failed, it cannot decide the package type and throws IllegalArgumentException wrapping the original NAR exception.

Solutions

  1. Provide the connector class name (className) so the loader can try the JAR path.
  2. Verify the package really is a NAR (correct manifest/descriptor) or repackage it with the proper NAR layout.
  3. Re-upload the package — the wrapped narClassLoaderException cause may show a corrupt/missing archive.
  4. Use the correct package type (built-in vs uploaded) for the component being registered.

Example fix

// before
// registering a plain jar without className
admin.sources().createSource(sourceConfig, jarPath); // config.className empty
// after
sourceConfig.setClassName("com.example.MyConnector");
admin.sources().createSource(sourceConfig, jarPath);
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the config carries a class name for non-NAR (jar) packages
if (config.getClassName() == null || config.getClassName().isEmpty()) {
    // only acceptable if the archive is a valid NAR
    try (java.util.jar.JarFile jf = new java.util.jar.JarFile(packagePath)) {
        // NAR archives contain the pulsar NAR manifest/metadata; absent -> require className
    }
}

Try / catch

try {
    getClassLoaderFromPackage(componentType, archivePath, ...);
} catch (IllegalArgumentException e) {
    log.error("Package {} unusable: provide className or fix NAR layout. Cause: {}",
        archivePath, e.getCause() != null ? e.getCause().getMessage() : e.getMessage());
}

Prevention

When it happens

Trigger: Registering/updating a connector or component whose package is neither a valid NAR nor resolvable: connectorClassName is empty and NarClassLoader construction failed (bad archive layout, missing nar metadata).

Common situations: Uploading a plain jar without specifying the class name; a jar mislabeled .nar missing the NAR manifest/descriptor; corrupted or partially uploaded package; wrong package type selected for the component.

Related errors


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

Appendix: source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionRuntimeCommon.java:76

        Exception jarClassLoaderException = null;
        Exception narClassLoaderException = null;

        try {
            try {
                jarClassLoader = ClassLoaderUtils.extractClassLoader(packageFile);
            } catch (Exception e) {
                jarClassLoaderException = e;
            }
            try {
                narClassLoader = extractNarClassLoader(packageFile, narExtractionDirectory);
            } catch (Exception e) {
                narClassLoaderException = e;
            }

            // if connector class name is not provided, we can only try to load archive as a NAR
            if (isEmpty(connectorClassName)) {
                if (narClassLoader == null) {
                    throw new IllegalArgumentException(String.format("%s package does not have the correct format. "
                                    + "Pulsar cannot determine if the package is a NAR package or JAR package. "
                                    + "%s classname is not provided and attempts to load it as a NAR package produced "
                                    + "the following error.",
                            FunctionCommon.capFirstLetter(componentType), FunctionCommon.capFirstLetter(componentType)),
                            narClassLoaderException);
                }
                try {
                    if (componentType == FunctionDetails.ComponentType.FUNCTION) {
                        connectorClassName = FunctionUtils.getFunctionClass(narClassLoader);
                    } else if (componentType == FunctionDetails.ComponentType.SOURCE) {
                        connectorClassName = ConnectorUtils.getIOSourceClass(narClassLoader);
                    } else {
                        connectorClassName = ConnectorUtils.getIOSinkClass(narClassLoader);
                    }
                } catch (IOException e) {
                    throw new IllegalArgumentException(String.format("Failed to extract %s class from archive",
                            componentType.toString().toLowerCase()), e);
                }

View on GitHub (pinned to 820761864e)