apache/iceberg · warning
Delete failed for {}: {}
Error message
Delete failed for {}: {} What it means
BaseSparkAction.deleteFiles runs file deletions in parallel via Tasks with failure suppression; when an individual delete fails, the onFailure handler logs 'Delete failed for <type>: <path>' with the exception and deletion continues for other files. The overall action may finish even though some files were not deleted, so orphan/obsolete files can remain.
Source
Thrown at spark/v4.1/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
- Inspect each logged path/exception to determine whether failures are transient and re-run the action
- Avoid concurrent delete actions on the same table (they race to delete the same files)
- Add retry/backoff or reduce delete concurrency if the storage layer is throttling
Defensive patterns
Strategy: retry
Try / catch
try {
Actions.forTable(table).rewriteDataFiles().execute();
} catch (Exception e) {
// check logs for 'Delete failed for <type>: <path>' entries and re-run
} Prevention
- Avoid overlapping delete actions on one table
- Ensure delete permissions on all relevant prefixes
- Tune executor/storage retry settings
When it happens
Trigger: deleteFunc (e.g. io.deleteFile) throws for a specific file during rewrite/expire actions — storage permissions issues, S3 throttling, or the file already being deleted by another process.
Common situations: Concurrent ExpireSnapshots/DeleteOrphanFiles runs racing each other; bucketing/permissions changes mid-run; transient S3 503s under heavy delete load.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Delete failed for {}: {}
- Cannot commit rewrite because of a ValidationException or Co
- Cannot commit rewrite because of a ValidationException or Co
- Cannot commit rewrite because of a ValidationException or Co
- Cannot commit rewrite because of a ValidationException or Co
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/6d51685235e94e98.
Report an issue: GitHub.