apache/pulsar · error · IllegalArgumentException
Invalid null namespace: ${namespace}
Error message
Invalid null namespace: ${namespace} What it means
NamespaceName.get(String) rejects null or empty namespace strings with IllegalArgumentException before consulting the cache. The namespace string must be a non-empty 'tenant/namespace' (or legacy V1) path.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java:58
private static final LoadingCache<String, NamespaceName> cache = CacheBuilder.newBuilder().maximumSize(100000)
.expireAfterAccess(30, TimeUnit.MINUTES).build(new CacheLoader<String, NamespaceName>() {
@Override
public NamespaceName load(String name) throws Exception {
return new NamespaceName(name);
}
});
public static final NamespaceName SYSTEM_NAMESPACE = NamespaceName.get("pulsar/system");
public static NamespaceName get(String tenant, String namespace) {
validateNamespaceName(tenant, namespace);
return get(tenant + '/' + namespace);
}
public static NamespaceName get(String namespace) {
if (namespace == null || namespace.isEmpty()) {
throw new IllegalArgumentException("Invalid null namespace: " + namespace);
}
try {
return cache.get(namespace);
} catch (ExecutionException e) {
throw (RuntimeException) e.getCause();
} catch (UncheckedExecutionException e) {
throw (RuntimeException) e.getCause();
}
}
public static Optional<NamespaceName> getIfValid(String namespace) {
NamespaceName ns = cache.getIfPresent(namespace);
if (ns != null) {
return Optional.of(ns);
}
if (namespace.length() == 0) {
return Optional.empty();View on GitHub (pinned to 820761864e)
Solutions
- Check the namespace string is non-null and non-empty before calling NamespaceName.get
- Fix upstream URL/config parsing so the tenant and namespace segments are populated
- Provide a default namespace when the caller's value may be absent
Example fix
// before
NamespaceName ns = NamespaceName.get(cfg.get("namespace")); // may be null
// after
String nsStr = cfg.get("namespace");
if (nsStr == null || nsStr.isEmpty()) { nsStr = "public/default"; }
NamespaceName ns = NamespaceName.get(nsStr); Defensive patterns
Strategy: type-guard
Validate before calling
boolean validNamespace(String ns) {
return ns != null && !ns.isEmpty() && ns.contains("/") && !ns.startsWith("/") && !ns.endsWith("/");
} Type guard
Optional<NamespaceName> tryGetNamespace(String ns) {
if (ns == null || ns.isEmpty()) {
return Optional.empty();
}
try {
return Optional.of(NamespaceName.get(ns));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
} Try / catch
try {
NamespaceName ns = NamespaceName.get(namespace);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Namespace must be non-empty '<tenant>/<namespace>', got: " + namespace, e);
} Prevention
- Validate URL/config parsing output before constructing NamespaceName
- Default to 'public/default' when a namespace value is absent
- Check for empty segments when splitting topic URLs on '/'
When it happens
Trigger: Calling NamespaceName.get(null) or NamespaceName.get("") directly, or via the two-argument get(tenant, namespace) where either component is null/empty; also hit by tests like testPushGetAndRemove that probe this path.
Common situations: Parsing topic URLs where the namespace segment is missing (e.g. 'persistent://tenant//topic'), config values left blank, split() producing empty components.
Related errors
- V1 namespace names (with cluster component) are no longer su
- Namespace name is not valid
- Tenant name or namespace is not valid
- ResourceGroupUpdate: Invalid null ResourceGroup config
- Invalid named entity: ${name}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/01c45e7c4d3a20bd.
Report an issue: GitHub.