apache/pulsar · error · IllegalArgumentException

Invalid package name '${packageName}'

Error message

Invalid package name '${packageName}'

What it means

The private PackageName constructor requires a fully qualified package name of the form <type>://<tenant>/<namespace>/<name>@<version>. This first check fires when the string contains no "://" separator, meaning no scheme/type portion was provided. PackageName.get is the public entry point that reaches this constructor.

Source

Thrown at pulsar-package-management/core/src/main/java/org/apache/pulsar/packages/management/core/common/PackageName.java:80

        return get(pkgName);
    }

    public static PackageName get(String type, String name, String version) {
        String pkgName = type + "://" + name + "@" + version;
        return get(pkgName);
    }

    public static PackageName get(String packageName) {
        try {
            return cache.get(packageName);
        } catch (ExecutionException e) {
            throw new RuntimeException(e.getCause());
        }
    }

    private PackageName(String packageName) {
        if (!packageName.contains("://")) {
            throw new IllegalArgumentException("Invalid package name '" + packageName + "'");
        }

        List<String> parts = Splitter.on("://").limit(2).splitToList(packageName);
        if (parts.size() != 2) {
            throw new IllegalArgumentException("Invalid package name '" + packageName + "'");
        }
        this.type = PackageType.getEnum(parts.get(0));

        String rest = parts.get(1);
        // if the package name does not contains '@', that means user does not set the version of package.
        // We will set the version to latest.
        if (!rest.contains("@")) {
            rest += "@";
        }
        parts = Splitter.on("@").splitToList(rest);
        if (parts.size() != 2) {
            throw new IllegalArgumentException("Invalid package name '" + packageName + "'");
        }

View on GitHub (pinned to 820761864e)

Solutions

  1. Prefix the name with its type scheme, e.g. "function://tenant/namespace/name@version".
  2. Validate the format before calling: must match type://tenant/namespace/name[@version].
  3. Check the package type (function/sink/source) and prepend it explicitly.

Example fix

// before
PackageName pkg = PackageName.get("tenant/ns/my-pkg@v1");
// after
PackageName pkg = PackageName.get("function://tenant/ns/my-pkg@v1");
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidPackageName(String name) {
    return name != null && name.matches("(function|sink|source)://[^/]+/[^/]+/[^/@]+(@[^@]+)?");
}

Try / catch

try {
    PackageName pkg = PackageName.get(input);
} catch (IllegalArgumentException e) {
    throw new RestException(Response.Status.BAD_REQUEST, "package name must be type://tenant/namespace/name[@version]");
}

Prevention

When it happens

Trigger: Calling PackageName.get("my-function") or get("tenant/ns/name@v1") — any string missing the "function://", "sink://", or "source://" scheme prefix.

Common situations: Users pass just the package name or path portion taken from docs/CLI output; forgetting the scheme when scripting with the REST API; mixing up package name with function name.

Related errors


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