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

  1. Check mqadmin topicRoute <topic>; restore write queues with mqadmin updateTopic -r 8 -w 8 -t <topic>.
  2. Verify the topic perm includes the WRITE bit (2; typical writable value 6).
  3. Ensure a master broker (brokerId=0) for the topic is running and registered (mqadmin clusterList).
  4. Confirm the topic name is correct and exists (mqadmin topicList).
  5. 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

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


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/9a3430e74fec58a3. Report an issue: GitHub.