{"record":{"id":"cdcb858de49c81b1","repo":"t8y2/dbx","slug":"partition-d-not-found-for-topic-s","errorCode":null,"errorMessage":"partition %d not found for topic %s","messagePattern":"partition (.+?) not found for topic (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/rocketmq/messages.go","lineNumber":362,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(targets) == 0 {\n\t\treturn nil, fmt.Errorf(\"no writable queue for topic %s\", topic)\n\t}\n\tpartition, hasPartition := optionalInt(params, \"partition\")\n\tselected := targets[0]\n\tif hasPartition {\n\t\tfound := false\n\t\tfor _, target := range targets {\n\t\t\tif target.QueueID == partition {\n\t\t\t\tselected = target\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\treturn nil, fmt.Errorf(\"partition %d not found for topic %s\", partition, topic)\n\t\t}\n\t}\n\tcommand := buildSendMessageCommand(topic, payload, selected.QueueID, params, time.Now().UnixMilli())\n\tresponse, err := invokeRemotingAllowCodes(ctx, selected.Address, config.ConnectTimeout, command, 0, 10, 11, 12)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tqueueID, _ := strconv.Atoi(response.ExtFields[\"queueId\"])\n\tqueueOffset, _ := strconv.ParseInt(response.ExtFields[\"queueOffset\"], 10, 64)\n\treturn map[string]any{\n\t\t\"ok\": true, \"topic\": topic, \"partition\": queueID,\n\t\t\"offset\": queueOffset, \"timestamp\": time.Now().UnixMilli(),\n\t}, nil\n}\n\nfunc buildSendMessageCommand(topic string, payload []byte, queueID int, params map[string]any, bornTimestamp int64) *remoting.RemotingCommand {\n\tmessage := primitive.NewMessage(topic, payload)\n\tmessage.WithProperty(primitive.PropertyUniqueClientMessageIdKeyIndex, primitive.CreateUniqID())","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/rocketmq/messages.go#L344-L380","documentation":"When sendMessage receives a 'partition' parameter, the driver looks for a target whose QueueID equals it among the topic's writable queues. If none matches, it refuses to send and returns this error. Queue IDs are 0-based and bounded by the topic's writeQueueNums.","triggerScenarios":"Calling sendMessage via dispatch with params['partition'] set to a queue ID that does not exist for the topic — negative, >= writeQueueNums, or a queue only on an excluded/non-writable broker.","commonSituations":"Caller hardcodes partition counts from another system (e.g. Kafka) exceeding RocketMQ queue count; writeQueueNums reduced after callers recorded IDs; off-by-one from treating IDs as 1-based; partition recorded from a different topic's route.","solutions":["Resolve valid IDs via mqadmin topicRoute <topic> (writeQueueNums); pass partition in 0..writeQueueNums-1.","Omit 'partition' to let the driver use the first available queue (targets[0]).","Restore shrunken queues: mqadmin updateTopic -w <n> -t <topic>.","Make callers re-resolve partition IDs against the current route instead of caching stale values.","Remember IDs are 0-based — a partition equal to writeQueueNums is out of range."],"exampleFix":"// before (topic has 8 queues)\ndispatch({\"action\": \"send\", \"topic\": \"myTopic\", \"partition\": 16})\n// after\ndispatch({\"action\": \"send\", \"topic\": \"myTopic\", \"partition\": 3})","handlingStrategy":"validation","validationCode":"// Validate partition against the topic's writeQueueNums before sending.\nroute, err := client.ExamineTopicRouteInfo(ctx, topic)\nif err != nil { return err }\nwriteQueues := 0\nfor _, qd := range route.QueueDatas { writeQueues = max(writeQueues, qd.WriteQueueNums) }\nif partition != nil && (*partition < 0 || *partition >= writeQueues) {\n    return fmt.Errorf(\"partition %d out of range 0..%d for topic %s\", *partition, writeQueues-1, topic)\n}","typeGuard":"func validPartition(partition, writeQueueNums int) bool {\n    return partition >= 0 && partition < writeQueueNums\n}","tryCatchPattern":null,"preventionTips":["Treat RocketMQ queue IDs as 0-based and bounded by writeQueueNums, not other systems' partition counts.","Fetch the route fresh before sending instead of caching partition IDs across topology changes.","Omit 'partition' when a specific queue isn't required; the driver picks targets[0].","Coordinate with producers that pin partition IDs when resizing topics."],"tags":["rocketmq","producer","queue","validation"],"backgroundTag":"partition-out-of-range","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}