apache/hadoop · error · IOException
Failed to move {path} to trash {trashPath}
Error message
Failed to move {path} to trash {trashPath} What it means
Thrown by TrashPolicyDefault.moveToTrash after two failed attempts to move the path into the trash (mkdirs + rename into .Trash/Current, with a timestamp suffix retry inside the loop). The original cause - the IOException from the last fs.rename - is attached, so the message tells you what was being moved where, and getCause() tells you why.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/TrashPolicyDefault.java:202
try {
// if the target path in Trash already exists, then append with
// a current time in millisecs.
String orig = trashPath.toString();
while(fs.exists(trashPath)) {
trashPath = new Path(orig + Time.now());
}
// move to current trash
fs.rename(path, trashPath,
Rename.TO_TRASH);
LOG.info("Moved: '" + path + "' to trash at: " + trashPath);
return true;
} catch (IOException e) {
cause = e;
}
}
throw new IOException("Failed to move " + path + " to trash " + trashPath,
cause);
}
@SuppressWarnings("deprecation")
@Override
public void createCheckpoint() throws IOException {
createCheckpoint(new Date());
}
@SuppressWarnings("deprecation")
public void createCheckpoint(Date date) throws IOException {
Collection<FileStatus> trashRoots = fs.getTrashRoots(false);
for (FileStatus trashRoot: trashRoots) {
LOG.info("TrashPolicyDefault#createCheckpoint for trashRoot: " +
trashRoot.getPath());
createCheckpoint(trashRoot.getPath(), date);
}
}View on GitHub (pinned to 2add963021)
Solutions
- Inspect the attached cause: AccessControlException -> fix .Trash ownership/permissions; QuotaExceededException -> raise quota or expunge; IOException disk full -> free space
- Run 'hadoop fs -expunge' (or empty .Trash) to make room, then retry the delete
- If the data must go now and trash is the blocker: re-run with -skipTrash after confirming permanent deletion is acceptable
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight the trash destination before deleting
Path trashRoot = fs.getTrashRoot(path);
if (!fs.exists(trashRoot)) {
fs.mkdirs(trashRoot, new FsPermission((short)0700));
}
// let quota/permission failures surface now with a clear context
fs.getFileStatus(trashRoot); Try / catch
try {
fs.delete(path, true);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Failed to move")) {
Throwable c = e.getCause(); // real reason: perms, quota, disk full
// fix per cause, expunge trash, then retry once
}
} Prevention
- Expunge trash and verify .Trash permissions/quota before large cleanup jobs
- The policy already retries twice; a second identical failure means an environmental cause - inspect getCause() instead of looping
When it happens
Trigger: Trash directory not creatable (permissions on user home), quota exceeded at the trash destination, disk full on the volume holding .Trash, or a pre-existing target that could not be renamed over. The two-iteration loop exists to survive a concurrent checkpoint renaming Current underneath it; anything failing both times is fatal.
Common situations: User home quota exhausted before a big cleanup; trash root owned by another user after UID changes; shared clusters where .Trash perms were tightened; deleting during a concurrent expunge.
Related errors
- Failed to checkpoint trash: {checkpoint}
- The operation is not allowed because there are mount points:
- Source path and dest path refer the same file or directory
- It is not allowed to rename a parent directory: %s to its su
- File: %s already exists
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/64949b605a3bf4f0.
Report an issue: GitHub.