apache/pulsar · error · IllegalArgumentException
Invalid namespace format. namespace: ${namespace}
Error message
Invalid namespace format. namespace: ${namespace} What it means
NamespaceName parses names in the V2 form '<tenant>/<namespace>'. This throw fires when the split on '/' yields anything other than 2 or 3 parts (e.g. no slash, or more than two slashes), i.e. the string is not a well-formed namespace name. It is immediately re-wrapped by the catch block with the fuller 'expected <tenant>/<namespace>' message, so callers normally see the wrapped variant.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java:104
@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() {
return localName;
}
public String getPersistentTopicName(String localTopic) {View on GitHub (pinned to 820761864e)
Solutions
- Format the name as '<tenant>/<namespace>' with exactly one slash, e.g. NamespaceName.get("public/default").
- Check the config/env source: if the value is null, empty, or missing the slash, fix the configuration before constructing the NamespaceName.
- If you have separate tenant and namespace strings, build with NamespaceName.get(tenant, namespace) instead of string concatenation.
- If you hold a legacy V1 name (tenant/cluster/namespace), migrate to the V2 form by dropping the cluster component.
Example fix
// before
NamespaceName ns = NamespaceName.get("my-tenant");
// after
NamespaceName ns = NamespaceName.get("my-tenant/my-namespace"); Defensive patterns
Strategy: validation
Validate before calling
boolean isValidNamespaceString(String ns) {
return ns != null && ns.chars().filter(c -> c == '/').count() == 1
&& !ns.startsWith("/") && !ns.endsWith("/");
}
// use: if (isValidNamespaceString(input)) NamespaceName.get(input); Type guard
static boolean isWellFormedNamespace(String ns) {
if (ns == null) return false;
String[] parts = ns.split("/", -1);
return parts.length == 2 && !parts[0].isEmpty() && !parts[1].isEmpty();
} Try / catch
try {
NamespaceName ns = NamespaceName.get(input);
} catch (IllegalArgumentException e) {
log.warn("Rejected namespace '{}': {}", input, e.getMessage());
// fail fast or substitute a validated default
} Prevention
- Always build namespaces from separate tenant/namespace variables via NamespaceName.get(tenant, ns) rather than string concatenation.
- Validate with NamespaceName.isValid(String) before calling get().
- Treat empty/absent config values as errors before they reach name construction.
When it happens
Trigger: Calling NamespaceName.get(String) or new via the public factory with a string containing zero '/' (e.g. 'my-tenant') or 4+ segments (e.g. 'a/b/c/d'), or with a null string (NPE caught and rethrown as this path's wrapper).
Common situations: Passing a bare topic or tenant name instead of tenant/namespace; reading a namespace from a config property/env var that was never set (yields 'null' or empty); concatenating tenant and namespace with the wrong separator; V1-style names edited incorrectly leaving extra slashes.
Related errors
- Invalid namespace format. expected <tenant>/<namespace> but
- Invalid namespace format. namespace: %s/%s
- ResourceGroupCreate: Invalid null ResourceGroup config
- ResourceGroupCreate: can't create resource group with an emp
- Invalid key-shared mode: ${keySharedMode}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/ddcff4eac8ffb1f8.
Report an issue: GitHub.