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

  1. Check the namespace string is non-null and non-empty before calling NamespaceName.get
  2. Fix upstream URL/config parsing so the tenant and namespace segments are populated
  3. 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

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


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