{"record":{"id":"7e2d77be4233e1b7","repo":"apache/pulsar","slug":"v1-namespace-names-with-cluster-component-are-no","errorCode":null,"errorMessage":"V1 namespace names (with cluster component) are no longer supported. Please use the V2 format: '<tenant>/<namespace>'. Got: ${namespace}","messagePattern":"V1 namespace names \\(with cluster component\\) are no longer supported\\. Please use the V2 format: '<tenant>/<namespace>'\\. Got: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java","lineNumber":100,"sourceCode":"        }\n\n        return Optional.of(get(namespace));\n    }\n\n    @SuppressFBWarnings(\"DCN_NULLPOINTER_EXCEPTION\")\n    private NamespaceName(String namespace) {\n        // Verify it's a proper namespace\n        // The namespace name is composed of <tenant>/<namespace>\n        try {\n\n            String[] parts = namespace.split(\"/\");\n            if (parts.length == 2) {\n                validateNamespaceName(parts[0], parts[1]);\n\n                tenant = parts[0];\n                localName = parts[1];\n            } else if (parts.length == 3) {\n                throw new IllegalArgumentException(\n                    \"V1 namespace names (with cluster component) are no longer supported. \"\n                    + \"Please use the V2 format: '<tenant>/<namespace>'. Got: \" + namespace);\n            } else {\n                throw new IllegalArgumentException(\"Invalid namespace format. namespace: \" + namespace);\n            }\n        } catch (IllegalArgumentException | NullPointerException e) {\n            throw new IllegalArgumentException(\"Invalid namespace format.\"\n                    + \" expected <tenant>/<namespace>\"\n                    + \" but got: \" + namespace, e);\n        }\n        this.namespace = namespace;\n    }\n\n    public String getTenant() {\n        return tenant;\n    }\n\n    public String getLocalName() {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java#L82-L118","documentation":"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.","triggerScenarios":"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.","commonSituations":"Migrating from old Pulsar clusters where topic URLs embed the cluster name, copied legacy configs, bookmarks/scripts generating old-style namespace strings.","solutions":["Strip the leading cluster segment and use the V2 format '<tenant>/<namespace>'","Update legacy topic/namespace URLs and configuration to drop the cluster component","Create the namespace under the V2 scheme (without cluster) if it does not exist yet"],"exampleFix":"// before\nNamespaceName ns = NamespaceName.get(\"cluster-a/tenant1/app1\"); // V1\n// after\nNamespaceName ns = NamespaceName.get(\"tenant1/app1\"); // V2, cluster segment removed","handlingStrategy":"validation","validationCode":"String[] parts = namespace.split(\"/\");\nif (parts.length == 3) {\n    // legacy V1 with cluster segment — normalize to V2\n    namespace = parts[1] + \"/\" + parts[2];\n}\nif (namespace.split(\"/\").length != 2) {\n    throw new IllegalArgumentException(\"Namespace must be V2 '<tenant>/<namespace>': \" + namespace);\n}","typeGuard":"boolean isV2Namespace(String ns) {\n    String[] p = ns == null ? new String[0] : ns.split(\"/\");\n    return p.length == 2 && !p[0].isEmpty() && !p[1].isEmpty();\n}","tryCatchPattern":"try {\n    NamespaceName ns = NamespaceName.get(namespace);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"V1 namespace names\")) {\n        String[] p = namespace.split(\"/\");\n        NamespaceName ns = NamespaceName.get(p[p.length - 2] + \"/\" + p[p.length - 1]);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Normalize legacy V1 cluster/tenant/namespace strings at config/URL ingestion time","Search your codebase and configs for three-segment namespace patterns","Document that cluster is encoded in serviceUrl, not in namespace names, for V2"],"tags":["namespace","validation","v1-format","migration","pulsar-common"],"backgroundTag":"legacy-v1-namespace-format","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}