apache/pulsar · error · IllegalArgumentException

Does not support topic domain:

Error message

Does not support topic domain: 

What it means

Thrown by TopicList.removeTopicDomainScheme when the given string prefix does not end with a recognized topic domain ('persistent' or 'non-persistent') and is not empty. The method can only strip a topic domain scheme it knows; any other ending prefix is rejected with this IllegalArgumentException.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/topics/TopicList.java:128

        s1.removeAll(list2);
        return s1;
    }

    public static String removeTopicDomainScheme(String originalRegexp) {
        if (!originalRegexp.toString().contains(SCHEME_SEPARATOR)) {
            return originalRegexp;
        }
        String[] parts = SCHEME_SEPARATOR_PATTERN.split(originalRegexp.toString());
        String prefix = parts[0];
        String removedTopicDomain = parts[1];
        if (prefix.equals(TopicDomain.persistent.value()) || prefix.equals(TopicDomain.non_persistent.value())) {
            prefix = "";
        } else if (prefix.endsWith(TopicDomain.non_persistent.value())) {
            prefix = prefix.substring(0, prefix.length() - TopicDomain.non_persistent.value().length());
        } else if (prefix.endsWith(TopicDomain.persistent.value())){
            prefix = prefix.substring(0, prefix.length() - TopicDomain.persistent.value().length());
        } else {
            throw new IllegalArgumentException("Does not support topic domain: " + prefix);
        }
        return prefix + removedTopicDomain;
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Only call removeTopicDomainScheme on strings that include the 'persistent://' or 'non-persistent://' scheme
  2. Check/normalize the input first (endsWith check or TopicName validation) and skip stripping when no domain is present
  3. Fix typos and casing in the domain portion before calling
  4. Handle domain-less topics separately instead of routing them through this method

Example fix

// before
String name = TopicList.removeTopicDomainScheme(topic); // topic = "my-tenant/ns/my-topic"
// after
String name = topic.startsWith("persistent://") || topic.startsWith("non-persistent://")
        ? TopicList.removeTopicDomainScheme(topic)
        : topic;
Defensive patterns

Strategy: validation

Validate before calling

if (topic.startsWith("persistent://") || topic.startsWith("non-persistent://")) {
    String stripped = TopicList.removeTopicDomainScheme(topic);
}

Type guard

static boolean hasTopicDomain(String topic) {
    return topic != null && (topic.startsWith("persistent://") || topic.startsWith("non-persistent://"));
}

Try / catch

try {
    stripped = TopicList.removeTopicDomainScheme(topic);
} catch (IllegalArgumentException e) {
    stripped = topic; // treat as already domain-less
}

Prevention

When it happens

Trigger: Calling removeTopicDomainScheme with a topic string or prefix that does not end in 'persistent/' or 'non-persistent/' — e.g. a plain topic name without a domain, a typo like 'persistant://', or a namespace-only string.

Common situations: Passing already-domain-stripped topics back into the function (double stripping); user-supplied topic lists mixing domainful and domain-less names; case mismatches ('Persistent://'); partitions or REST paths that omit the domain; custom tooling building topic names by hand.

Related errors


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