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

  1. Check the SQS queue permissions and credentials for DeleteMessageBatch
  2. Reduce read throughput / increase SQS queue capacity to avoid throttling
  3. Ensure messages are deleted within the visibility timeout window
  4. 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

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/4af20b559f21450a. Report an issue: GitHub.