apache/iceberg · warning · RuntimeException

Interrupted when waiting for deletions to complete

Error message

Interrupted when waiting for deletions to complete

What it means

RuntimeException thrown by S3FileIO.deleteFiles when the thread waiting on the batch deletion tasks is interrupted. The method re-interrupts the current thread, cancels all outstanding deletion tasks, and wraps the InterruptedException in a RuntimeException. It signals the caller's shutdown/interrupt rather than an S3 problem.

Source

Thrown at aws/src/main/java/org/apache/iceberg/aws/s3/S3FileIO.java:264

        Future<List<String>> deletionTask =
            executorService()
                .submit(() -> deleteBatch(clientForStoragePath("s3://" + bucket), bucket, keys));
        deletionTasks.add(deletionTask);
      }

      int totalFailedDeletions = 0;

      for (Future<List<String>> deletionTask : deletionTasks) {
        try {
          List<String> failedDeletions = deletionTask.get();
          failedDeletions.forEach(path -> LOG.warn("Failed to delete object at path {}", path));
          totalFailedDeletions += failedDeletions.size();
        } catch (ExecutionException e) {
          LOG.warn("Caught unexpected exception during batch deletion: ", e.getCause());
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          deletionTasks.stream().filter(task -> !task.isDone()).forEach(task -> task.cancel(true));
          throw new RuntimeException("Interrupted when waiting for deletions to complete", e);
        }
      }

      if (totalFailedDeletions > 0) {
        throw new BulkDeletionFailureException(totalFailedDeletions);
      }
    }
  }

  private void tagFileToDelete(PrefixedS3Client client, String path, Set<Tag> deleteTags)
      throws S3Exception {
    S3URI location = new S3URI(path, client.s3FileIOProperties().bucketToAccessPointMapping());
    String bucket = location.bucket();
    String objectKey = location.key();
    GetObjectTaggingRequest getObjectTaggingRequest =
        GetObjectTaggingRequest.builder().bucket(bucket).key(objectKey).build();
    GetObjectTaggingResponse getObjectTaggingResponse =
        client.s3().getObjectTagging(getObjectTaggingRequest);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Avoid interrupting the thread during deleteFiles; ensure graceful shutdown lets cleanup finish or accepts partial deletion (S3 deletes are per-object, retryable).
  2. Re-run the deletion — file deletes are idempotent for already-deleted keys; re-invoke deleteFiles after the interruption.
  3. If interruption is expected (job cancellation), catch RuntimeException at the call site and check Thread.currentThread().isInterrupted() to restore/record the interrupt state.
  4. Move large bulk deletions to a dedicated lifecycle/expiration job less likely to be interrupted.

Example fix

// before
io.deleteFiles(filesToDelete); // running inside a cancellable Spark task, interrupted on job kill
// after
try {
  io.deleteFiles(filesToDelete);
} catch (RuntimeException e) {
  if (Thread.currentThread().isInterrupted()) {
    LOG.warn("Deletion interrupted, will retry on restart", e);
  } else {
    throw e;
  }
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  io.deleteFiles(paths);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().contains("Interrupted when waiting for deletions")) {
    Thread.currentThread().interrupt(); // preserve interrupt status
    LOG.warn("Bulk deletion interrupted; deletes are idempotent, retry later");
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: deleteFiles (also invoked via deletePrefix) waiting on futures of S3 batch deletion tasks when the executing thread is interrupted — e.g. task cancellation in Spark/Flink, executor shutdown, or Thread.interrupt() during cleanup.

Common situations: Cancelling a Spark job whose ExpireSnapshots/deleteFiles cleanup is in flight; shutting down an executor while bulk deletes are running; a query killed by a timeout mechanism that interrupts threads; Flink task manager failover interrupting cleanup threads.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/35f709869c6398f6. Report an issue: GitHub.