apache/beam · error · IOException
Failed to delete pendingDeletes.size() messages after retrie
Error message
Failed to delete pendingDeletes.size() messages after retries retries
What it means
SqsUnboundedReader.deleteBatch retries deleting message batches up to BATCH_OPERATION_MAX_RETIRES; if pendingDeletes is still non-empty after exhausting retries it throws IOException 'Failed to delete N messages after R retries'. Messages were read but their receipt handles could not be deleted from the queue in time.
Source
Thrown at sdks/java/io/amazon-web-services2/src/main/java/org/apache/beam/sdk/io/aws2/sqs/SqsUnboundedReader.java:589
* <p>CAUTION: May be invoked from a separate thread.
*/
private void deleteBatch(List<String> receiptHandles) throws IOException {
int retries = 0;
FunctionWithIndex<String, DeleteMessageBatchRequestEntry> buildEntry =
(handle, id) ->
DeleteMessageBatchRequestEntry.builder()
.id(Long.toString(id))
.receiptHandle(handle)
.build();
Map<String, DeleteMessageBatchRequestEntry> pendingDeletes =
mapWithIndex(receiptHandles.stream(), buildEntry).collect(toMap(e -> e.id(), identity()));
while (!pendingDeletes.isEmpty()) {
if (retries >= BATCH_OPERATION_MAX_RETIRES) {
throw new IOException(
"Failed to delete "
+ pendingDeletes.size()
+ " messages after "
+ retries
+ " retries");
}
DeleteMessageBatchResponse result =
sqsClient.deleteMessageBatch(
DeleteMessageBatchRequest.builder()
.queueUrl(queueUrl())
.entries(pendingDeletes.values())
.build());
Map<Boolean, Set<String>> failures =
result.failed().stream()
.collect(partitioningBy(this::isHandleInvalid, mapping(e -> e.id(), toSet())));
View on GitHub (pinned to 12126d8942)
Solutions
- Check the SQS queue permissions and credentials for DeleteMessageBatch
- Reduce read throughput / increase SQS queue capacity to avoid throttling
- Ensure messages are deleted within the visibility timeout window
- Inspect AWS-side failures (CloudWatch metrics) and transient errors; messages will reappear after visibility timeout so downstream processing must be idempotent
Example fix
// before // visibility timeout of 30s with batch processing taking minutes // after // changeVisibilityTimeout(queueUrl, Duration.ofMinutes(10)); // or process/delete batches well within the visibility window
Defensive patterns
Strategy: retry
Validate before calling
// pre-check queue accessibility before reading sqs.getQueueUrl(GetQueueUrlRequest.builder().queueName(name).build());
Try / catch
try { reader.deleteBatch(handles); } catch (IOException e) { /* messages will reappear after visibility timeout; ensure idempotent processing */ } Prevention
- Make message processing idempotent since failed deletes cause redelivery
- Keep visibility timeout comfortably larger than batch processing time
- Monitor SQS NumberOfMessagesDeleted and throttling metrics
- Verify IAM permissions for sqs:DeleteMessageBatch
When it happens
Trigger: SQS DeleteMessageBatch repeatedly failing/partially failing (transient AWS errors, invalid/expired receipt handles, throttling) across all retry attempts while the reader keeps retrying.
Common situations: Long-running reads where visibility timeout expired and receipt handles became stale; SQS throttling under high throughput; temporary AWS outage/credential issues during deletes.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Error matching file spec %s: status %s
- Unable to read file(s) after retrying %d times
- Kinesis backend failed. Wait some time and retry.
- to(queueUrl) or to(dynamicDestination) is required
- Failed to extend visibility timeout for messages.size() mess
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/4af20b559f21450a.
Report an issue: GitHub.