[Bug] Proxy gRPC batch send returns one receipt for N messages, so SDKs fail the send although the broker stored the batch
Before Creating the Bug Report
- I found a bug, not just a question.
- I searched open GitHub Issues and pull requests and found no duplicate.
- I confirmed that this bug belongs to Apache RocketMQ.
Runtime platform environment
All platforms; reproduced with a deterministic unit test on the current develop branch.
RocketMQ version
develop at ff8f6f74c
JDK Version
All
Describe the Bug
The v2 gRPC protocol defines SendMessageResponse.entries as one SendResultEntry per message of the request. The proxy, however, sends an N-message SendMessageRequest to the broker as one remoting batch send and forwards the single batch SendResult to SendMessageActivity#convertToSendMessageResponse, which builds exactly one response entry:
LocalMessageService#sendMessagecollapsesmsgList.size() > 1into oneMessageBatchand returns a single-elementList<SendResult>.ClusterMessageService#sendMessagecallssendMessageAsync(..., msgList, ...)formsgList.size() != 1, which also returns oneSendResult(comma-joined per-message ids, first message's queue offset).convertToSendMessageResponseiterates the result list one-to-one, so an N-message request gets a 1-entry response.
Every official v2 SDK validates the receipt count: rocketmq-clients Java ProducerImpl#send0 fails the send future with InternalErrorException("[Bug] due to an unknown reason from remote, received send receipt's quantity ... is not equal to sent message's quantity ...") when sendReceipts.size() != messages.size(). So although the broker has already stored all N messages, the caller sees the send fail — and the SDK's automatic retry sends the whole batch again, duplicating every message.
Steps to Reproduce
- Send a
SendMessageRequestwith 3 messages through the proxy (gRPC v2, local or cluster mode). - Observe the broker stored 3 messages, but
SendMessageResponse.entrieshas size 1 (offset = only the first message's, messageId = comma-joined batch ids). - rocketmq-clients Java/Go/C++/C# producers reject the response with the receipt-quantity error and retry, storing the batch a second time.
What Did You Expect to See?
SendMessageResponse.entries must contain one entry per request message, with the per-message messageId and queueOffset + i, the same way the remoting client expands batch results (ProduceAccumulator#splitSendResults).
What Did You See Instead?
One entry for the whole batch; SDKs fail the send although it was persisted, and retries duplicate the batch.
Additional Context
The client module already contains the intended expansion algorithm (ProduceAccumulator#splitSendResults: split comma-joined msgId/offsetMsgId, queueOffset + i per entry, and reuse the single result for inner-batch-message responses without per-message ids). Applying the same expansion in SendMessageActivity#convertToSendMessageResponse (where the original request is available) fixes local and cluster mode at once, and a regression test in SendMessageActivityTest fails on unmodified develop.
Corresponding PR
- PR apache/rocketmq#11050
Source: apache/rocketmq