{"record":{"id":"5a10f75bba648fd9","repo":"apache/iceberg","slug":"failed-to-delete-file-5a10f7","errorCode":null,"errorMessage":"Failed to delete file {}","messagePattern":"Failed to delete file (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"azure/src/main/java/org/apache/iceberg/azure/adlsv2/ADLSFileIO.java","lineNumber":206,"sourceCode":"      LOG.warn(\n          \"Unable to load metrics class: '{}', falling back to null metrics\", DEFAULT_METRICS_IMPL);\n    }\n  }\n\n  @Override\n  public void deleteFiles(Iterable<String> pathsToDelete) throws BulkDeletionFailureException {\n    // Azure batch operations are not supported in all cases, e.g. with a user\n    // delegation SAS token, so avoid using it for now\n\n    AtomicInteger failureCount = new AtomicInteger();\n    Tasks.foreach(pathsToDelete)\n        .executeWith(ThreadPools.getWorkerPool())\n        .noRetry()\n        .suppressFailureWhenFinished()\n        .onFailure(\n            (file, exc) -> {\n              failureCount.incrementAndGet();\n              LOG.warn(\"Failed to delete file {}\", file, exc);\n            })\n        .run(this::deleteFile);\n\n    if (failureCount.get() > 0) {\n      throw new BulkDeletionFailureException(failureCount.get());\n    }\n  }\n\n  @Override\n  public Iterable<FileInfo> listPrefix(String prefix) {\n    ADLSLocation location = new ADLSLocation(prefix);\n\n    ListPathsOptions options = new ListPathsOptions();\n    options.setPath(location.path());\n    options.setRecursive(true);\n\n    return () -> {\n      try {","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/azure/src/main/java/org/apache/iceberg/azure/adlsv2/ADLSFileIO.java#L188-L224","documentation":"ADLSFileIO.deleteFiles() bulk-deletes paths in parallel via Tasks; each per-file failure increments a counter and is logged at WARN. If any deletion failed, a BulkDeletionFailureException carrying the failure count is thrown after the batch completes.","triggerScenarios":"Bulk deleting files where some paths are missing, permission-restricted, or hit transient ADLS errors; partial failures mixed with successes.","commonSituations":"Expiring snapshots whose some manifests were already removed; role changes mid-operation; throttling from ADLS during large cleanup batches.","solutions":["Inspect the per-file WARN logs to identify failing paths","Grant the identity delete permission (Storage Blob Data Contributor) on the container","Retry the operation — already-deleted files may succeed or be tolerated depending on caller","Reduce parallelism if ADLS throttling causes failures"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"for (String p : paths) {\n  // validate paths and permissions before bulk delete\n  Preconditions.checkArgument(p.startsWith(location), \"Path outside table location: %s\", p);\n}","typeGuard":null,"tryCatchPattern":"try {\n  io.deleteFiles(paths);\n} catch (BulkDeletionFailureException e) {\n  LOG.warn(\"{} files failed to delete; inspect WARN logs and retry\", e.failedCount());\n}","preventionTips":["Ensure identity has delete rights on the container","Retry failed bulk deletes; tolerate already-deleted files","Throttle parallelism if ADLS throttling is the failure cause"],"tags":["azure","adls","bulk-delete","partial-failure"],"backgroundTag":"file-delete-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}