apache/pulsar · error · IllegalArgumentException
${topic} is invalid
Error message
${topic} is invalid What it means
When toFullTopicName receives a string without '://', it treats it as a relative/short name and splits it by '/'. If the split yields a number of segments other than 1 (a bare short name) or 3 (tenant/namespace/topic), the method throws this IllegalArgumentException — the relative form is neither a short name nor a full tenant/ns/topic triple.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:571
final List<String> parts = splitBySlash(topic.substring(index + "://".length()), 4);
if (parts.size() == 4) {
throw new IllegalArgumentException(
"V1 topic names (with cluster component) are no longer supported. "
+ "Please use the V2 format: '<domain>://tenant/namespace/topic'. Got: " + topic);
}
if (parts.size() != 3) {
throw new IllegalArgumentException(topic + " is invalid. "
+ "Expected format: '<domain>://tenant/namespace/topic'");
}
NamespaceName.validateNamespaceName(parts.get(0), parts.get(1));
if (StringUtils.isBlank(parts.get(2))) {
throw new IllegalArgumentException(topic + " has blank local topic");
}
return topic; // it's a valid full topic name
} else {
List<String> parts = splitBySlash(topic, 0);
if (parts.size() != 1 && parts.size() != 3) {
throw new IllegalArgumentException(topic + " is invalid");
}
if (parts.size() == 1) {
if (StringUtils.isBlank(parts.get(0))) {
throw new IllegalArgumentException(topic + " has blank local topic");
}
return "persistent://public/default/" + parts.get(0);
} else {
NamespaceName.validateNamespaceName(parts.get(0), parts.get(1));
if (StringUtils.isBlank(parts.get(2))) {
throw new IllegalArgumentException(topic + " has blank local topic");
}
return "persistent://" + topic;
}
}
}
private static List<String> splitBySlash(String topic, int limit) {
final List<String> tokens = new ArrayList<>(3);View on GitHub (pinned to 820761864e)
Solutions
- Use either a bare topic name ('my-topic') or the complete triple ('tenant/namespace/topic') without the domain scheme, or a full URL with '://'
- Fix the number of path segments in the input
- Prefer the fully qualified 'persistent://tenant/ns/topic' form to avoid ambiguity
Example fix
// before
TopicName.toFullTopicName("my-tenant/my-topic");
// after
TopicName.toFullTopicName("my-tenant/my-ns/my-topic"); Defensive patterns
Strategy: validation
Validate before calling
public static boolean isShortOrTripleName(String s) {
if (s == null || s.contains("://")) return false;
int n = s.split("/").length;
return n == 1 || n == 3;
} Try / catch
try {
String full = TopicName.toFullTopicName(raw);
} catch (IllegalArgumentException e) {
log.error("'{}' is invalid: use a bare topic name or 'tenant/namespace/topic'", raw);
} Prevention
- Only use the documented relative forms: 'topic' or 'tenant/ns/topic'
- Prefer full URLs (with '://') to remove ambiguity
- Don't pass tenant-only or namespace-only paths as topic names
When it happens
Trigger: Calling toFullTopicName() with names like 'my-tenant/my-topic' (2 segments) or 'a/b/c/d' (4+ segments) that contain no '://' scheme.
Common situations: Hand-built topic strings with partial paths; passing a namespace-only or tenant-only path; copy-paste of a path fragment from a URL without the domain prefix; confusion between the 1-segment and 3-segment shortcut forms.
Related errors
- ${topic} is invalid. Expected format: '<domain>://tenant/nam
- Invalid topic name: %s. Topic local name must not be blank.
- Invalid topic name: ${completeTopicName}
- V1 topic names (with cluster component) are no longer suppor
- ${topic} has blank local topic
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/31aeec9864893569.
Report an issue: GitHub.