openimsdk/open-im-server · error

topic %s groupID not found

Error message

topic %s groupID not found

What it means

GetTopicConsumer resolves a logical topic name to its real Kafka topic and an associated consumer group ID via two internal maps. This error is thrown when the topic exists in logicalTopic but has no entry in topicGroupID, meaning the builder registered the topic mapping without ever recording a consumer group for it. It signals an inconsistent internal registration state rather than a Kafka-side problem.

Source

Thrown at pkg/mqbuild/builder.go:170

	topicGroupID map[string]string
}

func (x *kafkaBuilder) GetTopicProducer(ctx context.Context, topic string) (mq.Producer, error) {
	realTopic, ok := x.logicalTopic[topic]
	if !ok {
		return nil, fmt.Errorf("topic %s not found", topic)
	}
	return kafka.NewKafkaProducerV2(x.config, x.addr, realTopic)
}

func (x *kafkaBuilder) GetTopicConsumer(ctx context.Context, topic string) (mq.Consumer, error) {
	realTopic, ok := x.logicalTopic[topic]
	if !ok {
		return nil, fmt.Errorf("topic %s not found", topic)
	}
	groupID, ok := x.topicGroupID[realTopic]
	if !ok {
		return nil, fmt.Errorf("topic %s groupID not found", realTopic)
	}
	return kafka.NewMConsumerGroupV2(ctx, x.config, groupID, []string{realTopic}, true)
}

View on GitHub (pinned to 175a7bb067)

Solutions

  1. Check how the builder populates topicGroupID and ensure the registration path for this topic also sets its consumer group ID before GetTopicConsumer is called.
  2. Verify your configuration includes a consumer group for every topic registered; fix or add the missing group entry.
  3. Log both maps (logicalTopic, topicGroupID) at startup and diff them to find the topic missing a group.
  4. As a defensive measure in your own code, validate the topic/group pair against your config before calling GetTopicConsumer.
  5. If the group is genuinely optional, change the builder to derive a default groupID (e.g. topic + "-group") instead of erroring.

Example fix

// before (builder init)
builder.RegisterTopic("chat")
// group registration forgotten

// after
builder.RegisterTopic("chat")
builder.SetGroupID("chat", "chat-consumer-group") // populates topicGroupID[realTopic]
Defensive patterns

Strategy: validation

Validate before calling

func topicReady(b *mqbuild.Builder, topic string) bool {
	real, ok := b.LogicalTopic(topic) // or reflect/inspect your registration API
	return ok && b.HasGroupID(real)
}
if !topicReady(builder, "chat") {
	return fmt.Errorf("topic %q has no consumer group configured", "chat")
}
_, err := builder.GetTopicConsumer(ctx, "chat")

Type guard

func hasConsumerGroup(realTopic string, groups map[string]string) bool {
	_, ok := groups[realTopic]
	return ok
}

Try / catch

cons, err := builder.GetTopicConsumer(ctx, topic)
if err != nil {
	if strings.Contains(err.Error(), "groupID not found") {
		// fall back: re-register group or surface config error
		return fmt.Errorf("misconfigured topic %s: %w", topic, err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling GetTopicConsumer(ctx, topic) for a topic that was added to logicalTopic (e.g. via a builder registration step) but whose group ID was never set in topicGroupID — typically when topic registration and group registration are done in separate calls and only the first ran, or the group ID was cleared/never configured for that topic.

Common situations: Partial configuration: a topic is declared in config but the consumer-group section for it is missing or misnamed; a builder was constructed programmatically where RegisterTopic was called without the corresponding group registration; refactor or version change where group IDs moved to a new map and legacy init code no longer populates it.

Related errors


AI-assisted analysis of openimsdk/open-im-server@175a7bb067 (2026-09-04). Data as JSON: /api/errors/b6c7a2abef911a9e. Report an issue: GitHub.