Skip to content

Fix duplicate DeleteMessageBatchRequestEntry ids when SQS redelivers a message within one ack batch#1654

Open
BK202503 wants to merge 1 commit into
awspring:mainfrom
BK202503:fix/sqs-ack-duplicate-batch-entry-id
Open

Fix duplicate DeleteMessageBatchRequestEntry ids when SQS redelivers a message within one ack batch#1654
BK202503 wants to merge 1 commit into
awspring:mainfrom
BK202503:fix/sqs-ack-duplicate-batch-entry-id

Conversation

@BK202503

Copy link
Copy Markdown

Summary

SqsAcknowledgementExecutor used MessageHeaderUtils.getId(message) — the Spring message id derived from the SQS messageId — as the DeleteMessageBatchRequestEntry.id. On a Standard queue, if the same SQS message is redelivered within one acknowledgement batch, two entries end up with the same id and AWS rejects the entire batch with BatchEntryIdsNotDistinctException. The reporter's analysis and full repro are in #1634.

Fix

Batch entry id is now a positional index into the snapshot list of messages passed to deleteMessageBatch. SQS only requires the id to be unique within a single request and doesn't otherwise interpret it, so a positional index is sufficient and keeps the mapping trivial.

Partial-failure correlation is updated accordingly: createPartialFailureException parses each BatchResultErrorEntry.id as an index into the ordered batch and buckets messages by index. If any returned id doesn't parse to a valid index — which shouldn't happen but preserves the previous defensive behaviour — the executor still returns the existing "cannot correlate all failure ids" case, treating every message as failed.

Tests

  • New regression test: shouldUseUniqueBatchEntryIdsWhenMessageIdIsDuplicated — two mock messages sharing the same Spring message id (via MessagingMessageHeaders with an explicit shared UUID) but with distinct receipt handles → asserts the captured DeleteMessageBatchRequest entries have distinct ids and preserve both receipt handles in order. Fails on main (BatchEntryIdsNotDistinctException path exercised), passes with this change.
  • Existing partial-failure test updated: shouldWrapPartialBatchFailure now uses id("0") (positional) instead of the message-header UUID.
  • Full sqs module test suite: 634 tests, 0 failures, 0 errors, 5 skipped (./mvnw -pl spring-cloud-aws-sqs -am test — includes localstack integration tests).

Fixes #1634

…a message within one ack batch

Standard SQS queues can redeliver the same message before the acknowledgement
batch is flushed. SqsAcknowledgementExecutor was using MessageHeaderUtils.getId
(the Spring message id derived from the SQS messageId) as the batch entry id,
so a duplicate delivery within the same batch produced two entries with the
same DeleteMessageBatchRequestEntry.id — AWS then rejected the whole batch
with BatchEntryIdsNotDistinctException.

Switch to a positional-index id. The batch entry id is only a request-local
correlation token, so a per-request unique value is sufficient. Partial-failure
correlation now maps failed ids back to messages by index; if AWS returns an
id that isn't a valid index the executor still falls back to the
"cannot correlate all failure ids" path.

Fixes awspring#1634

Signed-off-by: BK202503 <199436087+BK202503@users.noreply.github.com>
@github-actions github-actions Bot added the component: sqs SQS integration related issue label Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: sqs SQS integration related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SQS batched acknowledgement can fail when a standard queue redelivers the same message in one ack batch

1 participant