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

  1. Provide either a bare topic name ('mytopic') or the full '<tenant>/<namespace>/<topic>' form ('public/default/mytopic').
  2. Remove duplicate/empty path segments (e.g. 'public//mytopic' -> 'public/default/mytopic').
  3. Verify the service URL and topic are supplied as separate fields — don't merge the broker URL and topic path.
  4. 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

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


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/9e1c58d09a67c96b. Report an issue: GitHub.