apache/hadoop · error · IOException
Failed to delete {pTask}
Error message
Failed to delete {pTask} What it means
During cleanUpPartialOutputForTask, the committer loops over earlier task-attempt directories (attempt 0..N-1 under the committed task path) and deletes each one. If FileSystem.delete(path, recursive=true) returns false AND the path still exists afterwards, it throws IOException('Failed to delete <path>') because a stale committed attempt could otherwise be double-committed later. This indicates the filesystem refused or partially performed the delete.
Source
Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/PartialFileOutputCommitter.java:101
throw new IllegalStateException("Invoking cleanUpPartialOutputForTask() " +
"from non @Preemptable class");
}
FileSystem fs =
fsFor(getTaskAttemptPath(context), context.getConfiguration());
LOG.info("cleanUpPartialOutputForTask: removing everything belonging to " +
context.getTaskAttemptID().getTaskID() + " in: " +
getCommittedTaskPath(context).getParent());
final TaskAttemptID taid = context.getTaskAttemptID();
final TaskID tid = taid.getTaskID();
Path pCommit = getCommittedTaskPath(context).getParent();
// remove any committed output
for (int i = 0; i < taid.getId(); ++i) {
TaskAttemptID oldId = new TaskAttemptID(tid, i);
Path pTask = new Path(pCommit, oldId.toString());
if (!fs.delete(pTask, true) && fs.exists(pTask)) {
throw new IOException("Failed to delete " + pTask);
}
}
}
}
View on GitHub (pinned to 2add963021)
Solutions
- Check permissions and ownership of the committed-task parent directory (the directory printed via getCommittedTaskPath(context).getParent()) and fix with chown/chmod.
- Verify the filesystem is healthy (out of safemode, no failover in progress) and retry the preemption cleanup.
- Look for a concurrent process deleting the same paths; if one exists, remove the race or accept that delete can return false because the path is already gone.
- As a last resort, manually remove the stale attempt directory named in the message and rerun.
Defensive patterns
Strategy: retry
Validate before calling
// before cleanup: prove the output tree is deletable by this user
Path parent = FileOutputCommitter.getCommittedTaskPath(context).getParent();
FileSystem fs = parent.getFileSystem(conf);
if (!fs.getFileStatus(parent).getPermission()
.getUserAction().implies(FsAction.WRITE)) {
throw new IOException("No write permission on " + parent + " - fix before cleanup");
} Try / catch
try {
committer.cleanUpPartialOutputForTask(context);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Failed to delete")) {
// transient FS state: verify health, fix permissions, then retry once
}
} Prevention
- Create output directories as the user the job runs as, or pre-chown them to that user.
- Do not run external cleanup scripts over committer-managed directories while tasks run.
- Treat delete-false-and-exists as a hard integrity error for this committer - never ignore and continue.
When it happens
Trigger: fs.delete(pTask, true) returning false while fs.exists(pTask) is true, for a previously committed attempt directory: no write/parent permission on the output tree, HDFS in safemode, a concurrent cleaner racing the delete, or a store returning inconsistent results.
Common situations: Output directory owned by a different user than the one running cleanup (e.g. yarn vs. submitter after a manual mkdir); HDFS safemode or namemode failover mid-operation; external scripts pruning the same directories; NFS/mount flakiness on the staging area.
Related errors
- Mkdirs failed to create {} (exists={}, cwd={})
- Permission denied: user=%s, path="%s":%s:%s:%s%s
- {} doesn't support modifyAclEntries
- {} doesn't support removeAclEntries
- {} doesn't support removeAcl
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/6608f322ff9ffee0.
Report an issue: GitHub.