apache/iceberg · warning

Bulk deletion failed for

Error message

Bulk deletion failed for {} of {} {} file(s)

What it means

A WARN from FileCleanupStrategy.deleteFiles (used by expireSnapshots and orphan/planning cleanup jobs) when bulk deletion via SupportsBulkOperations reports BulkDeletionFailureException: a subset of the pathsToDelete could not be deleted, with counts given in the message. Cleanup proceeds as best-effort; the failed files remain on storage until a future cleanup run deletes them.

Solutions

  1. Re-run expireSnapshots/cleanup — already-deleted files are skipped and remaining ones retried.
  2. Throttle cleanup concurrency or run during off-peak hours to avoid provider rate limiting.
  3. Ensure only one cleanup job runs per table at a time to avoid racing deletions.
  4. Review IAM policies for delete permission on the data and metadata prefixes.

Example fix

// before: overlapping expire jobs
spark.submit(expireJob); anotherClient.expireSnapshots(table);
// after: serialize cleanup runs
if (lockAcquired(table)) {
  SparkActions.get().expireSnapshots(table).olderThan(ts).execute();
}
Defensive patterns

Strategy: retry

Try / catch

try { actions.expireSnapshots(table).olderThan(ts).execute(); } catch (RuntimeException e) { /* re-run; deletes are idempotent */ }

Prevention

When it happens

Trigger: expireSnapshots (or similar cleanup) with a bulk-capable FileIO; the object store's bulk delete fails for some objects — throttling, permissions on individual keys, objects concurrently deleted by another cleanup job, or batch failures in the S3/GCS client.

Common situations: Snapshot expiration under aggressive S3 rate limits; overlapping expireSnapshots jobs from different clients; bucket policies denying deletes for certain prefixes; large batches exceeding provider batch limits.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/FileCleanupStrategy.java:112

  protected CloseableIterable<ManifestFile> readManifests(Snapshot snapshot) {
    if (snapshot.manifestListLocation() != null) {
      return InternalData.read(
              FileFormat.AVRO, fileIO.newInputFile(snapshot.manifestListLocation()))
          .setRootType(GenericManifestFile.class)
          .project(MANIFEST_PROJECTION)
          .reuseContainers()
          .build();
    } else {
      return CloseableIterable.withNoopClose(snapshot.allManifests(fileIO));
    }
  }

  protected void deleteFiles(Set<String> pathsToDelete, String fileType) {
    if (deleteFunc == null && fileIO instanceof SupportsBulkOperations) {
      try {
        ((SupportsBulkOperations) fileIO).deleteFiles(pathsToDelete);
      } catch (BulkDeletionFailureException e) {
        LOG.warn(
            "Bulk deletion failed for {} of {} {} file(s)",
            e.numberFailedObjects(),
            pathsToDelete.size(),
            fileType,
            e);
      } catch (RuntimeException e) {
        LOG.warn("Bulk deletion failed", e);
      }
    } else {
      Consumer<String> deleteFuncToUse = deleteFunc == null ? defaultDeleteFunc : deleteFunc;

      Tasks.foreach(pathsToDelete)
          .executeWith(deleteExecutorService)
          .retry(3)
          .stopRetryOn(NotFoundException.class)
          .stopOnFailure()
          .suppressFailureWhenFinished()
          .onFailure(

View on GitHub (pinned to 86d9c8fc54)