risingwavelabs/risingwave · error
Invalid short topic name '{}', it should be in the format of
Error message
Invalid short topic name '{}', it should be in the format of <tenant>/<namespace>/<topic> or <topic> What it means
Pulsar topic names are normalized to a 'persistent://tenant/namespace/topic' form. Short names with 1 or 3 '/'-separated segments are accepted; any other segmentation (0, 2, or 4+ parts) is ambiguous and rejected at parse time.
Source
Thrown at src/connector/src/source/pulsar/topic.rs:128
/// The short topic name can be:
/// - `<topic>`
/// - `<tenant>/<namespace>/<topic>`
///
/// The fully qualified topic name can be:
/// `<domain>://<tenant>/<namespace>/<topic>`
pub fn parse_topic(topic: &str) -> Result<Topic> {
let mut complete_topic = topic.to_owned();
if !topic.contains("://") {
let parts: Vec<&str> = topic.split('/').collect();
complete_topic = match parts.len() {
1 => format!(
"{}://{}/{}/{}",
PERSISTENT_DOMAIN, PUBLIC_TENANT, DEFAULT_NAMESPACE, parts[0],
),
3 => format!("{}://{}", PERSISTENT_DOMAIN, topic),
_ => {
bail!(
"Invalid short topic name '{}', \
it should be in the format of <tenant>/<namespace>/<topic> or <topic>",
topic
);
}
};
}
let parts: Vec<&str> = complete_topic.splitn(2, "://").collect();
let domain = match parts[0] {
PERSISTENT_DOMAIN | NON_PERSISTENT_DOMAIN => parts[0],
_ => {
bail!(
"The domain only can be specified as 'persistent' or 'non-persistent'. Input domain is '{}'",
parts[0]
);
}View on GitHub (pinned to 6469eb736d)
Solutions
- Provide either a bare topic name ('mytopic') or the full '<tenant>/<namespace>/<topic>' form ('public/default/mytopic').
- Remove duplicate/empty path segments (e.g. 'public//mytopic' -> 'public/default/mytopic').
- Verify the service URL and topic are supplied as separate fields — don't merge the broker URL and topic path.
- Trim trailing slashes and whitespace before passing the topic string.
Example fix
// before
let topic = Topic::new("persistent://public/default")?; // 3 path pieces but no topic
// after
let topic = Topic::new("persistent://public/default/mytopic")?; Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_pulsar_topic(t: &str) -> bool {
let t = t.trim_end_matches('/');
let segs = t.split('/').filter(|s| !s.is_empty()).count();
segs == 1 || segs == 3
} Type guard
fn normalize_pulsar_topic(input: &str) -> Option<String> {
let parts: Vec<&str> = input.split('/').filter(|s| !s.is_empty()).collect();
match parts.len() {
1 => Some(format!("persistent://public/default/{}", parts[0])),
3 => Some(format!("persistent://{}/{}", parts[0], format!("{}/{}/{}", parts[0], parts[1], parts[2]).splitn(2, "//").last().unwrap())),
_ => None,
}
} Try / catch
match Topic::new(input) {
Err(e) if e.to_string().contains("Invalid short topic name") => eprintln!("use <topic> or <tenant>/<namespace>/<topic>"),
other => other,
} Prevention
- Use either the bare topic name or full tenant/namespace/topic form; never 2 or 4 segments.
- Keep the broker service URL and topic string in separate config fields.
- Trim trailing slashes and reject empty path segments in user input.
- Prefer fully qualified 'persistent://public/default/<topic>' names in production configs.
When it happens
Trigger: Calling parse_topic (indirectly via Topic::new) with a topic string like 'a//b', 'tenant/namespace' (2 segments), 'a/b/c/d' (4 segments), or other malformed names.
Common situations: Typing the Pulsar URL with a missing or extra path segment ('pulsar://tenant/topic'); leaving trailing slashes; copying a full 'persistent://tenant/namespace/topic' into a field expecting only the short name plus extra segments; using 'non-persistent' domains incorrectly at this parse layer.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- invalid partition index number
- credentials_url must be a valid URL (s3://, file://) or an a
- invalid credentials_url scheme '{}', only file://, s3://, an
- Url::parse error: {e}
- HTTP sink requires url option when schema has exactly 1 colu
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/9e1c58d09a67c96b.
Report an issue: GitHub.