t8y2/dbx · error
read topic config %s: %v; fallback snapshot: %w
Error message
read topic config %s: %v; fallback snapshot: %w
What it means
readTopicConfig first tries to fetch the single topic's config directly from the broker; when that request fails (err), it falls back to fetching the broker's full topic-config snapshot (fetchAllTopicConfigs). This error is raised only when BOTH paths fail, wrapping the direct error and the fallback error together.
Source
Thrown at agents/drivers/rocketmq/topics.go:587
}
if err := json.Unmarshal(repairRocketMQJSON(response.Body), &wrapper); err != nil {
return nil, err
}
return wrapper.TopicConfigTable, nil
}
func readTopicConfig(ctx context.Context, address, topic string) (*topicConfigWire, error) {
response, err := invokeRemotingWithClient(ctx, address, remoting.NewRequest(remoting.GetTopicConfig, map[string]string{"topic": topic}))
if err == nil {
var config topicConfigWire
if decodeErr := json.Unmarshal(repairRocketMQJSON(response.Body), &config); decodeErr != nil {
return nil, decodeErr
}
return &config, nil
}
configs, fallbackErr := fetchAllTopicConfigs(ctx, address)
if fallbackErr != nil {
return nil, fmt.Errorf("read topic config %s: %v; fallback snapshot: %w", topic, err, fallbackErr)
}
config := configs[topic]
if config == nil {
return nil, fmt.Errorf("topic config not found: %s", topic)
}
if config.TopicName == "" {
config.TopicName = topic
}
return config, nil
}
func topicAttributesString(attributes map[string]string) string {
keys := sortedKeys(attributes)
parts := make([]string, 0, len(keys))
for _, key := range keys {
if !strings.HasPrefix(key, "+") && !strings.HasPrefix(key, "-") {
continue
}View on GitHub (pinned to c0390bff16)
Solutions
- Read both wrapped errors: the first (%v) is the direct per-topic fetch failure, the second (%w) is the snapshot failure — fix the root cause indicated by the fallback error
- Check master broker health/reachability at the resolved address (port 10911 remoting) and retry once the broker is back
- Increase config.RequestTimeout if the broker is slow but healthy
- Verify ACL credentials permit GET_TOPIC_CONFIG and GET_ALL_TOPIC_CONFIG admin operations
Example fix
// before
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
cfg, err := readTopicConfig(ctx, address, name)
// after
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // larger window
defer cancel()
cfg, err := readTopicConfig(ctx, address, name)
if err != nil {
// log both wrapped errors; the second is the broker snapshot failure
log.Printf("readTopicConfig failed: %v", err)
return retryWithBackoff(func() error { _, err = readTopicConfig(ctx, address, name); return err })
} Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", address, 3*time.Second)
if err != nil {
return fmt.Errorf("broker %s unreachable, skip config read", address)
}
conn.Close() Type guard
func isReadTopicConfigErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "read topic config") && strings.Contains(err.Error(), "fallback snapshot")
} Try / catch
cfg, err := readTopicConfig(ctx, address, topic)
if err != nil {
if isReadTopicConfigErr(err) {
time.Sleep(backoff)
cfg, err = readTopicConfig(ctx, address, topic)
}
if err != nil { return err }
} Prevention
- Increase RequestTimeout for slow or heavily loaded brokers
- Avoid altering topic config during broker rolling restarts
- Ensure ACLs allow both GET_TOPIC_CONFIG and GET_ALL_TOPIC_CONFIG
- Parse both wrapped errors to identify which request path failed
When it happens
Trigger: updatePartitions, getTopicConfig, or alterTopicConfig calls readTopicConfig for a topic while the broker is unreachable or erroring, and the fallback getAllTopicConfig snapshot request also fails (network failure, broker restart, permission rejection).
Common situations: Broker master temporarily down during a rolling restart; remoting timeout due to network congestion; broker rejecting the admin request due to ACL/permission changes; both requests fired within the same short request timeout window during a broker GC pause.
Related errors
- no RocketMQ master broker found for topic %s
- query messages for topic %s on all masters: %w
- invalid queue offset: %w
- query topic stats for %s on all masters: %w
- no RocketMQ master broker found
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/1ac45ffc05184dae.
Report an issue: GitHub.