{"record":{"id":"9e1c58d09a67c96b","repo":"risingwavelabs/risingwave","slug":"invalid-short-topic-name-it-should-be-in-the","errorCode":null,"errorMessage":"Invalid short topic name '{}', it should be in the format of <tenant>/<namespace>/<topic> or <topic>","messagePattern":"Invalid short topic name '(.+?)', it should be in the format of <tenant>/<namespace>/<topic> or <topic>","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/source/pulsar/topic.rs","lineNumber":128,"sourceCode":"/// The short topic name can be:\n/// - `<topic>`\n/// - `<tenant>/<namespace>/<topic>`\n///\n/// The fully qualified topic name can be:\n/// `<domain>://<tenant>/<namespace>/<topic>`\npub fn parse_topic(topic: &str) -> Result<Topic> {\n    let mut complete_topic = topic.to_owned();\n\n    if !topic.contains(\"://\") {\n        let parts: Vec<&str> = topic.split('/').collect();\n        complete_topic = match parts.len() {\n            1 => format!(\n                \"{}://{}/{}/{}\",\n                PERSISTENT_DOMAIN, PUBLIC_TENANT, DEFAULT_NAMESPACE, parts[0],\n            ),\n            3 => format!(\"{}://{}\", PERSISTENT_DOMAIN, topic),\n            _ => {\n                bail!(\n                    \"Invalid short topic name '{}', \\\n                it should be in the format of <tenant>/<namespace>/<topic> or <topic>\",\n                    topic\n                );\n            }\n        };\n    }\n\n    let parts: Vec<&str> = complete_topic.splitn(2, \"://\").collect();\n\n    let domain = match parts[0] {\n        PERSISTENT_DOMAIN | NON_PERSISTENT_DOMAIN => parts[0],\n        _ => {\n            bail!(\n                \"The domain only can be specified as 'persistent' or 'non-persistent'. Input domain is '{}'\",\n                parts[0]\n            );\n        }","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/source/pulsar/topic.rs#L110-L146","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet topic = Topic::new(\"persistent://public/default\")?; // 3 path pieces but no topic\n// after\nlet topic = Topic::new(\"persistent://public/default/mytopic\")?;","handlingStrategy":"validation","validationCode":"fn is_valid_pulsar_topic(t: &str) -> bool {\n    let t = t.trim_end_matches('/');\n    let segs = t.split('/').filter(|s| !s.is_empty()).count();\n    segs == 1 || segs == 3\n}","typeGuard":"fn normalize_pulsar_topic(input: &str) -> Option<String> {\n    let parts: Vec<&str> = input.split('/').filter(|s| !s.is_empty()).collect();\n    match parts.len() {\n        1 => Some(format!(\"persistent://public/default/{}\", parts[0])),\n        3 => Some(format!(\"persistent://{}/{}\", parts[0], format!(\"{}/{}/{}\", parts[0], parts[1], parts[2]).splitn(2, \"//\").last().unwrap())),\n        _ => None,\n    }\n}","tryCatchPattern":"match Topic::new(input) {\n    Err(e) if e.to_string().contains(\"Invalid short topic name\") => eprintln!(\"use <topic> or <tenant>/<namespace>/<topic>\"),\n    other => other,\n}","preventionTips":["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."],"tags":["pulsar","topic","url","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}