apache/pulsar · error · IllegalArgumentException
invalid null domain
Error message
invalid null domain
What it means
NamespaceName.getTopicName(domain, topic) composes 'domain://namespace/topic' and throws this IllegalArgumentException when the TopicDomain argument is null. It is a defensive programmer-error check: a null domain cannot produce a valid topic URL.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java:135
public String getLocalName() {
return localName;
}
public String getPersistentTopicName(String localTopic) {
return getTopicName(TopicDomain.persistent, localTopic);
}
/**
* Compose the topic name from namespace + topic.
*
* @param domain
* @param topic
* @return
*/
String getTopicName(TopicDomain domain, String topic) {
if (domain == null) {
throw new IllegalArgumentException("invalid null domain");
}
NamedEntity.checkName(topic);
return String.format("%s://%s/%s", domain.toString(), namespace, topic);
}
@Override
public String toString() {
return namespace;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof NamespaceName) {
NamespaceName other = (NamespaceName) obj;
return Objects.equals(namespace, other.namespace);
}
return false;View on GitHub (pinned to 820761864e)
Solutions
- Pass an explicit TopicDomain, typically TopicDomain.persistent for normal topics, e.g. namespace.getPersistentTopicName(topic).
- If the domain comes from a string, map it defensively: TopicDomain.valueOf(str) with a null/empty check or default to persistent.
- Check whether the calling code path should have used a higher-level TopicName API instead of constructing the name manually.
Example fix
// before TopicDomain domain = lookupDomain(cfg); // may return null String name = ns.getTopicName(domain, topic); // after TopicDomain domain = Optional.ofNullable(lookupDomain(cfg)).orElse(TopicDomain.persistent); String name = ns.getTopicName(domain, topic);
Defensive patterns
Strategy: type-guard
Validate before calling
if (domain == null) {
domain = TopicDomain.persistent; // or reject the input earlier
}
String name = ns.getTopicName(domain, topic); Type guard
static TopicDomain requireDomain(TopicDomain d) {
if (d == null) throw new IllegalArgumentException("TopicDomain is required");
return d;
} Try / catch
try {
String name = ns.getTopicName(domain, topic);
} catch (IllegalArgumentException e) {
if ("invalid null domain".equals(e.getMessage())) {
domain = TopicDomain.persistent;
} else {
throw e;
}
} Prevention
- Prefer getPersistentTopicName(topic) over the generic getTopicName(domain, topic) when the domain is always persistent.
- Use an enum with a well-defined default instead of a nullable TopicDomain variable.
- Never let domain strings from config map to null; use valueOf with fallback handling.
When it happens
Trigger: Invoking getPersistentTopicName / package-private getTopicName with a null TopicDomain, e.g. passing an unset enum variable or the result of a lookup that returned null instead of TopicDomain.persistent.
Common situations: Code that resolves TopicDomain from config or a string via valueOf with a null input; refactored code where a domain constant became null; building topic names generically where the domain parameter is optional elsewhere but required here.
Related errors
- Invalid topic name: '${topicName}'. Topic name must not have
- ResourceGroupCreate: Invalid null ResourceGroup config
- ResourceGroupCreate: can't create resource group with an emp
- Invalid key-shared mode: ${keySharedMode}
- Failed to add schema to an active topic with empty(BYTES) sc
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/4ad849b339101dcd.
Report an issue: GitHub.