apache/pulsar · error · IllegalArgumentException

Invalid topic name ${topic}

Error message

Invalid topic name ${topic}

What it means

splitBySlash is TopicName's internal tokenizer used by toFullTopicName to split a topic string into path segments. It rejects strings containing empty segments (consecutive slashes, e.g. 'a//b') and strings ending with a trailing slash (nothing after the last '/'), throwing 'Invalid topic name <topic>' because empty tokens would silently produce malformed topic names.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:600

                }
                return "persistent://" + topic;
            }
        }
    }

    private static List<String> splitBySlash(String topic, int limit) {
        final List<String> tokens = new ArrayList<>(3);
        final int loopCount = (limit <= 0) ? Integer.MAX_VALUE : limit - 1;
        int beginIndex = 0;
        for (int i = 0; i < loopCount; i++) {
            final int endIndex = topic.indexOf('/', beginIndex);
            if (endIndex < 0) {
                tokens.add(topic.substring(beginIndex));
                return tokens;
            } else if (endIndex > beginIndex) {
                tokens.add(topic.substring(beginIndex, endIndex));
            } else {
                throw new IllegalArgumentException("Invalid topic name " + topic);
            }
            beginIndex = endIndex + 1;
        }
        if (beginIndex >= topic.length()) {
            throw new IllegalArgumentException("Invalid topic name " + topic);
        }
        tokens.add(topic.substring(beginIndex));
        return tokens;
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Remove duplicate/trailing slashes so each '/'-separated segment is non-empty
  2. Normalize the topic string (e.g. collapse '//' to '/' and strip a trailing '/') before passing it
  3. Use a full, well-formed 'persistent://tenant/ns/topic' URL

Example fix

// before
TopicName.toFullTopicName("persistent://public/default//my-topic/");
// after
String t = raw.replaceAll("/+", "/").replaceAll("/$", "");
TopicName.toFullTopicName(t); // persistent://public/default/my-topic
Defensive patterns

Strategy: validation

Validate before calling

public static boolean hasNoEmptySegments(String s) {
    return s != null && !s.contains("//") && !s.endsWith("/") && !s.startsWith("/");
}

Try / catch

try {
    String full = TopicName.toFullTopicName(raw);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Invalid topic name")) {
        raw = raw.replaceAll("/+", "/").replaceAll("/$", "");
        full = TopicName.toFullTopicName(raw);
    }
}

Prevention

When it happens

Trigger: Any toFullTopicName() call whose input contains consecutive slashes or a trailing slash, e.g. 'persistent://tenant//topic' or 'tenant/ns/topic/' — splitBySlash hits an empty token and throws. The message surfaces as 'Invalid topic name <topic>'.

Common situations: URL-join logic that appends or duplicates slashes; base-URL + path concatenation bugs ('.../default/' + '/topic'); users pasting REST paths with trailing slashes; template substitution leaving empty segments.

Related errors


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