apache/iceberg · warning

Delete failed for

Error message

Delete failed for {}: {}

What it means

A logged warning emitted per-file by BaseSparkAction.deleteFiles when deleting data/manifest files with Tasks.foreach + suppressFailureWhenFinished and an onFailure handler. Each deletion failure (with its exception and file path/type) is recorded but does not abort the rest of the batch, so a few failed deletes leave orphan files behind while the action otherwise succeeds.

Solutions

  1. Re-run the action; failed deletes leave files that a subsequent DeleteOrphanFiles pass will pick up.
  2. Fix IAM/storage permissions so the credential used can delete objects under the table location.
  3. Check the chained exception per file: 404 means the file is already gone (safe to ignore); 403 is a permissions fix.
  4. Avoid running two delete/expire jobs concurrently on the same table.
  5. Enable retries or reduce concurrency on the delete executor to work around rate limiting.

Example fix

// before
.deleteFunc.accept(path);  // throws per-file, logged and suppressed
// after
// re-run deleteFiles/ExpireSnapshots after fixing permissions:
// SparkActions.get(spark).deleteOrphanFiles().olderThan(ts).execute();  // picks up orphaned leftovers
Defensive patterns

Strategy: retry

Validate before calling

// ensure the job principal can delete under the table location before running actions
// (pre-check with a harmless write/delete in a test prefix)

Try / catch

try { action.execute(); } catch (Exception e) { /* inspect per-file onFailure logs; re-run action */ }

Prevention

When it happens

Trigger: Running actions such as DeleteOrphanFiles, RewriteDataFiles, or ExpireSnapshots that invoke BaseSparkAction.deleteFiles, when deleteFunc.accept(path) throws for individual files — permission errors, concurrent deletion by another job, object-store 404s/403s, or transient S3 errors.

Common situations: ExpireSnapshots racing with a concurrent delete job; IAM policies lacking s3:DeleteObject on some prefixes; files already removed by an earlier run (double deletion); rate limiting on bulk object-store deletes.

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

Appendix: source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/actions/BaseSparkAction.java:255

   * @param deleteFunc a delete func
   * @param files an iterator of Spark rows of the structure (path: String, type: String)
   * @return stats on which files were deleted
   */
  protected DeleteSummary deleteFiles(
      ExecutorService executorService, Consumer<String> deleteFunc, Iterator<FileInfo> files) {

    DeleteSummary summary = new DeleteSummary();

    Tasks.foreach(files)
        .retry(DELETE_NUM_RETRIES)
        .stopRetryOn(NotFoundException.class)
        .suppressFailureWhenFinished()
        .executeWith(executorService)
        .onFailure(
            (fileInfo, exc) -> {
              String path = fileInfo.getPath();
              String type = fileInfo.getType();
              LOG.warn("Delete failed for {}: {}", type, path, exc);
            })
        .run(
            fileInfo -> {
              String path = fileInfo.getPath();
              String type = fileInfo.getType();
              deleteFunc.accept(path);
              summary.deletedFile(path, type);
            });

    return summary;
  }

  protected DeleteSummary deleteFiles(SupportsBulkOperations io, Iterator<FileInfo> files) {
    DeleteSummary summary = new DeleteSummary();
    Iterator<List<FileInfo>> fileGroups = Iterators.partition(files, DELETE_GROUP_SIZE);

    Tasks.foreach(fileGroups)
        .suppressFailureWhenFinished()

View on GitHub (pinned to 86d9c8fc54)