apache/pulsar · error · IllegalArgumentException
Invalid namespace format. namespace: %s/%s
Error message
Invalid namespace format. namespace: %s/%s
What it means
NamespaceName.validateNamespaceName(tenant, namespace) validates the two components of a V2 namespace name. It throws this IllegalArgumentException when either the tenant or the namespace part is null or empty, formatting them as 'tenant/namespace' in the message. After the null/empty check it also runs NamedEntity.checkName on both parts.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java:163
@Override
public boolean equals(Object obj) {
if (obj instanceof NamespaceName) {
NamespaceName other = (NamespaceName) obj;
return Objects.equals(namespace, other.namespace);
}
return false;
}
@Override
public int hashCode() {
return namespace.hashCode();
}
public static void validateNamespaceName(String tenant, String namespace) {
if ((tenant == null || tenant.isEmpty()) || (namespace == null || namespace.isEmpty())) {
throw new IllegalArgumentException(
String.format("Invalid namespace format. namespace: %s/%s", tenant, namespace));
}
NamedEntity.checkName(tenant);
NamedEntity.checkName(namespace);
}
@Override
public NamespaceName getNamespaceObject() {
return this;
}
@Override
public boolean includes(TopicName topicName) {
return this.equals(topicName.getNamespaceObject());
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Supply both a non-null, non-empty tenant and namespace, e.g. NamespaceName.get("public", "default").
- Trim/normalize inputs from config and treat empty strings as missing values before constructing.
- If components come from splitting a string, verify the string contains a non-empty segment on each side of '/'.
- Use NamespaceName.isValid or try-catch around construction when input origin is untrusted.
Example fix
// before
String tenant = config.get("tenant"); // ""
NamespaceName ns = NamespaceName.get(tenant, "default");
// after
String tenant = config.get("tenant");
NamespaceName ns = (tenant == null || tenant.isEmpty())
? NamespaceName.get("public", "default")
: NamespaceName.get(tenant, "default"); Defensive patterns
Strategy: validation
Validate before calling
void requireNonEmpty(String v, String what) {
if (v == null || v.isEmpty()) {
throw new IllegalArgumentException(what + " must be non-empty");
}
}
// call before: requireNonEmpty(tenant, "tenant"); requireNonEmpty(localName, "namespace");
NamespaceName.validateNamespaceName(tenant, localName); Type guard
static boolean hasValidComponents(String tenant, String ns) {
return tenant != null && !tenant.isEmpty() && ns != null && !ns.isEmpty();
} Try / catch
try {
NamespaceName.validateNamespaceName(tenant, localName);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Both tenant and namespace must be non-empty; got tenant='" + tenant + "' namespace='" + localName + "'", e);
} Prevention
- Normalize empty config strings to null and fail with a clear message naming the missing key.
- Call validateNamespaceName proactively in admin/CLI layers before any API call.
- When splitting 'a/b' strings, use split("/", -1) and reject empty segments explicitly.
When it happens
Trigger: Calling NamespaceName.get(tenant, namespace) with null or empty tenant, or null or empty namespace — e.g. NamespaceName.get(null, "default") or NamespaceName.get("public", ""). Also triggered from the NamespaceName(String) parsing path when a segment of a 'a/b' name is empty (e.g. 'public/' or '/default').
Common situations: Configuration where tenant or namespace keys are unset and default to empty strings; splitting a namespace string that has an empty segment; templated service URLs where variables were not substituted; programmatic client construction with unset builder fields.
Related errors
- ResourceGroupCreate: Invalid null ResourceGroup config
- ResourceGroupCreate: can't create resource group with an emp
- Invalid namespace format. namespace: ${namespace}
- Invalid namespace format. expected <tenant>/<namespace> but
- Invalid topic name: '${topicName}'. Topic name must not have
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/7f27c48dd06ed8d2.
Report an issue: GitHub.