t8y2/dbx · error
no writable queue for topic %s
Error message
no writable queue for topic %s
What it means
sendMessage calls messageQueueTargets with writable=true, which intersects the route's QueueDatas (WriteQueueNums, WRITE perm) with each broker's master address. If no queue can be assembled, there is nowhere to send the message and this error is returned.
Source
Thrown at agents/drivers/rocketmq/messages.go:348
func (a *rocketMQAgent) sendMessage(params map[string]any) (any, error) {
topic, err := requireString(params, "topic")
if err != nil {
return nil, err
}
payload, err := decodePayload(params)
if err != nil {
return nil, err
}
client, config, _ := a.requireClient()
ctx, cancel := context.WithTimeout(context.Background(), config.RequestTimeout)
defer cancel()
targets, err := a.messageQueueTargets(ctx, client, topic, true)
if err != nil {
return nil, err
}
if len(targets) == 0 {
return nil, fmt.Errorf("no writable queue for topic %s", topic)
}
partition, hasPartition := optionalInt(params, "partition")
selected := targets[0]
if hasPartition {
found := false
for _, target := range targets {
if target.QueueID == partition {
selected = target
found = true
break
}
}
if !found {
return nil, fmt.Errorf("partition %d not found for topic %s", partition, topic)
}
}
command := buildSendMessageCommand(topic, payload, selected.QueueID, params, time.Now().UnixMilli())
response, err := invokeRemotingAllowCodes(ctx, selected.Address, config.ConnectTimeout, command, 0, 10, 11, 12)View on GitHub (pinned to c0390bff16)
Solutions
- Check mqadmin topicRoute <topic>; restore write queues with mqadmin updateTopic -r 8 -w 8 -t <topic>.
- Verify the topic perm includes the WRITE bit (2; typical writable value 6).
- Ensure a master broker (brokerId=0) for the topic is running and registered (mqadmin clusterList).
- Confirm the topic name is correct and exists (mqadmin topicList).
- Create the topic explicitly with mqadmin updateTopic instead of relying on autoCreateTopicEnable.
Example fix
// before: read-only topic mqadmin updateTopic -n namesrv:9876 -t myTopic -r 8 -w 0 -p 4 // after: restore write queues and permission mqadmin updateTopic -n namesrv:9876 -t myTopic -r 8 -w 8 -p 6
Defensive patterns
Strategy: validation
Validate before calling
// Before sending, confirm the topic has writable queues.
route, err := client.ExamineTopicRouteInfo(ctx, topic)
if err != nil { return err }
masters := map[string]bool{}
for _, bd := range route.BrokerDatas {
if a := bd.BrokerAddrs["0"]; a != "" { masters[bd.BrokerName] = true }
}
writable := 0
for _, qd := range route.QueueDatas {
if masters[qd.BrokerName] && qd.Perm&2 != 0 { writable += qd.WriteQueueNums }
}
if writable == 0 {
return fmt.Errorf("topic %s is not writable; check writeQueueNums/perm", topic)
} Type guard
func topicWritable(route *admin.TopicRoute) bool {
masters := map[string]bool{}
for _, bd := range route.BrokerDatas {
if a := bd.BrokerAddrs["0"]; a != "" { masters[bd.BrokerName] = true }
}
for _, qd := range route.QueueDatas {
if masters[qd.BrokerName] && qd.Perm&2 != 0 && qd.WriteQueueNums > 0 {
return true
}
}
return false
} Prevention
- Create topics explicitly with mqadmin updateTopic and matching read/write queue counts (e.g. -r 8 -w 8).
- Never set perm to read-only (4) while producers are active.
- Monitor master broker liveness so you know when sends can't be routed.
- Validate topic names against mqadmin topicList before dispatching sends.
When it happens
Trigger: Calling sendMessage via dispatch for a topic whose route has zero writable queues: writeQueueNums 0 on all QueueDatas, WRITE perm bit cleared, no master address for any listed broker, or QueueDatas with no matching BrokerDatas.
Common situations: Topic set read-only during maintenance (perm=4); writeQueueNums shrunk to 0; master broker down so no '0' address; typo in topic name resolving to a non-writable route; incomplete auto-created topic route.
Related errors
- no RocketMQ master broker found for topic %s
- no RocketMQ master broker found for topic %s
- partition %d not found for topic %s
- RocketMQ agent is not connected
- decode ACL list: %w
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/9a3430e74fec58a3.
Report an issue: GitHub.