apache/iceberg · warning

Deleted only {} of {} files using bulk deletes

Error message

Deleted only {} of {} files using bulk deletes

What it means

A logged warning emitted by DeleteOrphanFilesSparkAction.deleteBulk when the FileIO's bulk delete (SupportsBulkOperations.deleteFiles) partially fails, signaled by BulkDeletionFailureException carrying the number of failed objects. The successfully deleted count is derived as paths.size() minus failures; remaining files are warned about but the action continues.

Source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/actions/DeleteOrphanFilesSparkAction.java:325

  }

  private void collectPathsForOutput(
      List<String> paths, List<String> orphanFileList, int maxSampleSize) {
    if (streamResults()) {
      int lengthToAdd = Math.min(maxSampleSize - orphanFileList.size(), paths.size());
      orphanFileList.addAll(paths.subList(0, lengthToAdd));
    } else {
      orphanFileList.addAll(paths);
    }
  }

  private void deleteBulk(SupportsBulkOperations io, List<String> paths) {
    try {
      io.deleteFiles(paths);
      LOG.info("Deleted {} files using bulk deletes", paths.size());
    } catch (BulkDeletionFailureException e) {
      int deletedFilesCount = paths.size() - e.numberFailedObjects();
      LOG.warn(
          "Deleted only {} of {} files using bulk deletes", deletedFilesCount, paths.size(), e);
    }
  }

  private void deleteNonBulk(List<String> paths) {
    Tasks.Builder<String> deleteTasks =
        Tasks.foreach(paths)
            .noRetry()
            .executeWith(deleteExecutorService)
            .suppressFailureWhenFinished()
            .onFailure((file, exc) -> LOG.warn("Failed to delete file: {}", file, exc));

    if (deleteFunc == null) {
      LOG.info(
          "Table IO {} does not support bulk operations. Using non-bulk deletes.",
          table.io().getClass().getName());
      deleteTasks.run(table.io()::deleteFile);
    } else {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Re-run deleteOrphanFiles; a second pass usually deletes the files that failed the first time.
  2. Fix the failing keys' permissions (check the exception detail / object-store server logs for 403/404).
  3. Reduce batch concurrency or enable S3 client retry/throttle mitigation for large sweeps.
  4. Avoid running overlapping orphan-file deletion jobs on the same table location.
  5. Refresh long-lived credentials or use instance profiles for multi-hour sweeps.

Example fix

// before
SparkActions.get(spark).deleteOrphanFiles().olderThan(ts).execute();  // partial bulk failure
// after
// inspect e.numberFailedObjects(), fix perms, then re-run the same action
SparkActions.get(spark).deleteOrphanFiles().olderThan(ts).execute();  // retry pass
Defensive patterns

Strategy: retry

Validate before calling

// confirm bulk support and credentials lifetime before sweeping
// io instanceof SupportsBulkOperations; STS session length > expected sweep duration

Try / catch

try { io.deleteFiles(paths); } catch (BulkDeletionFailureException e) { /* re-run for the failed objects */ }

Prevention

When it happens

Trigger: Running DeleteOrphanFiles against a FileIO with bulk support (e.g., S3FileIO) where io.deleteFiles(paths) deletes some objects but fails on others — expired/short-lived credentials mid-batch, per-object permission errors, missing objects already deleted, or object-store throttling.

Common situations: STS credentials expiring during a long orphan-file sweep; mixed-prefix bucket policies where some keys are undeletable; concurrent DeleteOrphanFiles runs deleting the same objects; S3 503 slow-down throttling on large batches.

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/558178556d92f919. Report an issue: GitHub.