apache/pulsar · error · IllegalArgumentException

V1 namespace names (with cluster component) are no longer su

Error message

V1 namespace names (with cluster component) are no longer supported. Please use the V2 format: '<tenant>/<namespace>'. Got: ${namespace}

What it means

The NamespaceName constructor parses 'tenant/namespace' strings. A three-part name (cluster/tenant/namespace — the legacy V1 format) is explicitly rejected because V1 namespaces with a cluster component are no longer supported; callers must use the V2 'tenant/namespace' format.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java:100

        }

        return Optional.of(get(namespace));
    }

    @SuppressFBWarnings("DCN_NULLPOINTER_EXCEPTION")
    private NamespaceName(String namespace) {
        // Verify it's a proper namespace
        // The namespace name is composed of <tenant>/<namespace>
        try {

            String[] parts = namespace.split("/");
            if (parts.length == 2) {
                validateNamespaceName(parts[0], parts[1]);

                tenant = parts[0];
                localName = parts[1];
            } else if (parts.length == 3) {
                throw new IllegalArgumentException(
                    "V1 namespace names (with cluster component) are no longer supported. "
                    + "Please use the V2 format: '<tenant>/<namespace>'. Got: " + namespace);
            } else {
                throw new IllegalArgumentException("Invalid namespace format. namespace: " + namespace);
            }
        } catch (IllegalArgumentException | NullPointerException e) {
            throw new IllegalArgumentException("Invalid namespace format."
                    + " expected <tenant>/<namespace>"
                    + " but got: " + namespace, e);
        }
        this.namespace = namespace;
    }

    public String getTenant() {
        return tenant;
    }

    public String getLocalName() {

View on GitHub (pinned to 820761864e)

Solutions

  1. Strip the leading cluster segment and use the V2 format '<tenant>/<namespace>'
  2. Update legacy topic/namespace URLs and configuration to drop the cluster component
  3. Create the namespace under the V2 scheme (without cluster) if it does not exist yet

Example fix

// before
NamespaceName ns = NamespaceName.get("cluster-a/tenant1/app1"); // V1
// after
NamespaceName ns = NamespaceName.get("tenant1/app1"); // V2, cluster segment removed
Defensive patterns

Strategy: validation

Validate before calling

String[] parts = namespace.split("/");
if (parts.length == 3) {
    // legacy V1 with cluster segment — normalize to V2
    namespace = parts[1] + "/" + parts[2];
}
if (namespace.split("/").length != 2) {
    throw new IllegalArgumentException("Namespace must be V2 '<tenant>/<namespace>': " + namespace);
}

Type guard

boolean isV2Namespace(String ns) {
    String[] p = ns == null ? new String[0] : ns.split("/");
    return p.length == 2 && !p[0].isEmpty() && !p[1].isEmpty();
}

Try / catch

try {
    NamespaceName ns = NamespaceName.get(namespace);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("V1 namespace names")) {
        String[] p = namespace.split("/");
        NamespaceName ns = NamespaceName.get(p[p.length - 2] + "/" + p[p.length - 1]);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Passing a V1-style namespace such as 'use-my-cluster/my-tenant/my-ns' to NamespaceName.get/constructor, or consuming legacy configuration/URLs that still contain the cluster segment.

Common situations: Migrating from old Pulsar clusters where topic URLs embed the cluster name, copied legacy configs, bookmarks/scripts generating old-style namespace strings.

Related errors


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