{"record":{"id":"c6ca716795280118","repo":"apache/pulsar","slug":"invalid-topic-domain-s","errorCode":null,"errorMessage":"Invalid topic domain: %s","messagePattern":"Invalid topic domain: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pulsar-function-go/pf/topicName.go","lineNumber":72,"sourceCode":"\t\t\ttopic = \"persistent://\" + topic\n\t\t} else if len(parts) == 1 {\n\t\t\ttopic = \"persistent://\" + publicTenant + \"/\" + defaultNamespace + \"/\" + parts[0]\n\t\t} else {\n\t\t\treturn nil, errors.New(\n\t\t\t\t\"Invalid short topic name '\" + topic +\n\t\t\t\t\t\"', it should be in the format of <tenant>/<namespace>/<topic> or <topic>\")\n\t\t}\n\t}\n\n\ttn := &TopicName{}\n\n\t// The fully qualified topic name can be in two different forms:\n\t// new:    persistent://tenant/namespace/topic\n\t// legacy: persistent://tenant/cluster/namespace/topic\n\tparts := strings.SplitN(topic, \"://\", 2)\n\tdomain := parts[0]\n\tif domain != \"persistent\" && domain != \"non-persistent\" {\n\t\treturn nil, errors.New(\"Invalid topic domain: \" + domain)\n\t}\n\ttn.Domain = domain\n\n\trest := parts[1]\n\tvar err error\n\n\t// The rest of the name can be in different forms:\n\t// new:    tenant/namespace/<localName>\n\t// legacy: tenant/cluster/namespace/<localName>\n\t// Examples of localName:\n\t// 1. some/name/xyz//\n\t// 2. /xyz-123/feeder-2\n\tparts = strings.SplitN(rest, \"/\", 4)\n\tif len(parts) == 3 {\n\t\t// New topic name without cluster name\n\t\ttn.Namespace = parts[0] + \"/\" + parts[1]\n\t} else if len(parts) == 4 {\n\t\t// Legacy topic name that includes cluster name","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-function-go/pf/topicName.go#L54-L90","documentation":"Topic-name parsing failure in the Go function runtime's ParseTopicName: after splitting on '://', the domain prefix is neither 'persistent' nor 'non-persistent' (the legacy 4-part cluster form is also handled separately), so the string is rejected as a topic name; the domain portion of the input string is the faulty input.","triggerScenarios":"Passing topics like 'kafka://my-topic', 'http://...', 'topic://x', or a typo such as 'persistant://tenant/ns/topic' to ParseTopicName.","commonSituations":"Copying URIs from other systems, typos in the scheme, or passing plain broker/service URLs instead of topic names.","solutions":["Use persistent:// or non-persistent:// as the topic scheme","Fix typos in the topic URI"],"exampleFix":"// before\npf.ParseTopicName(\"kafka://my-tenant/ns/my-topic\")\n// after\npf.ParseTopicName(\"persistent://my-tenant/ns/my-topic\")","handlingStrategy":"validation","validationCode":"if i := strings.Index(topic, \"://\"); i >= 0 && topic[:i] != \"persistent\" && topic[:i] != \"non-persistent\" {\n    return fmt.Errorf(\"unsupported domain %q\", topic[:i])\n}","typeGuard":"func isPulsarTopic(t string) bool { return strings.HasPrefix(t, \"persistent://\") || strings.HasPrefix(t, \"non-persistent://\") }","tryCatchPattern":"tn, err := pf.ParseTopicName(topic)\nif err != nil {\n    return fmt.Errorf(\"invalid topic domain in %q: %w\", topic, err)\n}","preventionTips":["Use only persistent:// or non-persistent:// schemes","Watch for scheme typos (persistant, persistence)","Do not pass foreign URIs (kafka://, http://) as Pulsar topics"],"tags":["go","topic-name","domain","validation"],"backgroundTag":"invalid-topic-domain","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}