apache/iceberg · warning

Delete failed for {}: {}

Error message

Delete failed for {}: {}

What it means

BaseSparkAction.deleteFiles removes manifest/data files in parallel via Tasks.foreach with an executor. Individual delete failures do not abort the whole run: this warning logs each failed file (type and path) with its exception, thanks to suppressFailureWhenFinished and the onFailure handler.

Source

Thrown at spark/v4.0/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)

Solutions

  1. Review the per-file warn logs to identify which paths failed and why (permissions vs transient).
  2. Grant the executing credentials delete permission on the storage location (e.g. s3:DeleteObject).
  3. Re-run the action after fixing transient issues — deletes are idempotent for already-gone files.
  4. Enable retries or reduce parallelism if the storage layer is throttling (Tasks retry config / executor size).
  5. Investigate anything not cleaned before removing the action's listing snapshot dependency.
Defensive patterns

Strategy: retry

Validate before calling

// Check delete permission before running the action
FileIO io = table.io();
try {
  io.deleteFile(samplePath); // or a canary object in the same location
} catch (Exception e) {
  throw new IllegalStateException("Credentials cannot delete files in " + location, e);
}

Try / catch

try {
  action.execute(result -> LOG.info("deleted {} files", result.deletedDataFilesCount()));
} catch (Exception e) {
  LOG.warn("Delete run had failures; inspect per-file warns and retry", e);
}

Prevention

When it happens

Trigger: Actions like RemoveOrphanFiles/DeleteReachableFiles deleting files where some individual deleteFunc.accept(path) calls throw (permission denied, object-store 403, concurrent deletion, network errors) while the executor service processes the file set.

Common situations: Deleting orphan files on S3 with a role lacking s3:DeleteObject; files already removed by a concurrent GC run; throttling/rate limits during mass deletion; HDFS permission mismatches.

Related errors


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