apache/pulsar · error

Invalid topic name: %s

Error message

Invalid topic name: %s

What it means

After expanding the domain, ParseTopicName splits the rest of the topic by '/'. Valid names have 3 parts (tenant/namespace/topic) or 4 (legacy tenant/cluster/namespace/topic). Anything else, e.g. missing namespace or extra segments, raises this error.

Source

Thrown at pulsar-function-go/pf/topicName.go:93

	rest := parts[1]
	var err error

	// The rest of the name can be in different forms:
	// new:    tenant/namespace/<localName>
	// legacy: tenant/cluster/namespace/<localName>
	// Examples of localName:
	// 1. some/name/xyz//
	// 2. /xyz-123/feeder-2
	parts = strings.SplitN(rest, "/", 4)
	if len(parts) == 3 {
		// New topic name without cluster name
		tn.Namespace = parts[0] + "/" + parts[1]
	} else if len(parts) == 4 {
		// Legacy topic name that includes cluster name
		tn.Namespace = fmt.Sprintf("%s/%s/%s", parts[0], parts[1], parts[2])
	} else {
		return nil, errors.New("Invalid topic name: " + topic)
	}

	tn.Name = topic
	tn.Partition, err = getPartitionIndex(topic)
	if err != nil {
		return nil, err
	}

	return tn, nil
}

// NameWithoutPartition returns the topic name, sans the partition portion
func (tn *TopicName) NameWithoutPartition() string {
	if tn.Partition < 0 {
		return tn.Name
	}
	idx := strings.LastIndex(tn.Name, partitionedTopicSuffix)
	if idx > 0 {

View on GitHub (pinned to 820761864e)

Solutions

  1. Format as persistent://<tenant>/<namespace>/<topic> (3 segments after scheme)
  2. For legacy clusters use persistent://<tenant>/<cluster>/<namespace>/<topic>
  3. Ensure no empty segments (double slashes) and no extra segments
  4. Print the topic string before parsing to verify substitution of templated values

Example fix

// before
pf.ParseTopicName("persistent://public/mytopic") // error
// after
pf.ParseTopicName("persistent://public/default/mytopic")
Defensive patterns

Strategy: validation

Validate before calling

rest := topic
if i := strings.Index(rest, "://"); i >= 0 { rest = rest[i+3:] }
n := len(strings.Split(rest, "/"))
if n != 3 && n != 4 { return fmt.Errorf("topic needs 3 or 4 path segments, got %d", n) }

Try / catch

tn, err := pf.ParseTopicName(topic)
if err != nil {
    return fmt.Errorf("invalid topic %q: %w", topic, err)
}

Prevention

When it happens

Trigger: Passing 'persistent://tenant/topic' (missing namespace) or a name with 5+ segments after the scheme; also empty tenant/namespace strings yielding empty parts.

Common situations: Hand-editing topic names, template placeholders left unfilled (e.g. 'persistent://{{tenant}}/{{ns}}/topic' partially substituted), or legacy vs new cluster naming confusion.

Related errors


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