apache/hadoop · error · IOException
Cannot move "{path}" to the trash, as it contains the trash
Error message
Cannot move "{path}" to the trash, as it contains the trash What it means
Thrown by TrashPolicyDefault.moveToTrash when the path being deleted is an ancestor of (or equal to) the trash root - i.e. deleting it would delete the trash itself. After verifying the path exists and is not already inside the trash, the policy checks trashRoot.getParent().toString().startsWith(qpath) and refuses with IOException. It prevents rm -r from destroying the safety net it is supposed to use.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/TrashPolicyDefault.java:149
public boolean moveToTrash(Path path) throws IOException {
if (!isEnabled())
return false;
if (!path.isAbsolute()) // make path absolute
path = new Path(fs.getWorkingDirectory(), path);
// check that path exists
fs.getFileStatus(path);
String qpath = fs.makeQualified(path).toString();
Path trashRoot = fs.getTrashRoot(path);
Path trashCurrent = new Path(trashRoot, CURRENT);
if (qpath.startsWith(trashRoot.toString())) {
return false; // already in trash
}
if (trashRoot.getParent().toString().startsWith(qpath)) {
throw new IOException("Cannot move \"" + path +
"\" to the trash, as it contains the trash");
}
Path trashPath = makeTrashRelativePath(trashCurrent, path);
Path baseTrashPath = makeTrashRelativePath(trashCurrent, path.getParent());
IOException cause = null;
// try twice, in case checkpoint between the mkdirs() & rename()
for (int i = 0; i < 2; i++) {
try {
if (!fs.mkdirs(baseTrashPath, PERMISSION)) { // create current
LOG.warn("Can't create(mkdir) trash directory: " + baseTrashPath);
return false;
}
} catch (FileAlreadyExistsException | ParentNotDirectoryException e) {
// find the path which is not a directory, and modify baseTrashPath
// & trashPath, then mkdirsView on GitHub (pinned to 2add963021)
Solutions
- Delete the specific subpaths that do not contain the trash, e.g. rm -r /user/alice/data instead of /user/alice
- If you truly intend to remove everything including trash: run 'hadoop fs -expunge' first, or delete with -skipTrash
- Guard admin scripts by refusing to rm -r any path that is a prefix of the user's trash root
Example fix
// before
fs.delete(new Path("/user/alice"), true); // contains /user/alice/.Trash
// after
Path trashRoot = fs.getTrashRoot(new Path("/user/alice"));
// delete children, excluding anything at or above the trash root
for (FileStatus st : fs.listStatus(new Path("/user/alice"))) {
if (!trashRoot.toString().startsWith(st.getPath().toString())) {
fs.delete(st.getPath(), true);
}
} Defensive patterns
Strategy: validation
Validate before calling
Path trashRoot = fs.getTrashRoot(path);
String qpath = fs.makeQualified(path).toString();
if (trashRoot.getParent() != null
&& trashRoot.getParent().toString().startsWith(qpath)) {
// would delete the trash itself: refuse or enumerate children instead
throw new IOException("Refusing to delete ancestor of trash: " + path);
}
fs.delete(path, true); Try / catch
try {
fs.delete(path, true);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("contains the trash")) {
// delete children individually, or use -skipTrash deliberately
}
} Prevention
- Never rm -r a user's home root or /user when trash is enabled; target concrete subdirectories
- In admin scripts, compare the delete path against getTrashRoot() and refuse prefixes
When it happens
Trigger: 'hadoop fs -rm -r /user' or 'rm -r /user/alice' when the trash root is /user/alice/.Trash; any delete of a high-level directory (home root, /user, /) that contains the .Trash directory of the current user.
Common situations: Admin cleanup scripts running rm -r on home directories; recursive deletes that walk up too far; users surprised that deleting their own home directory is blocked.
Related errors
- Failed to get server trash configuration
- Directory {} is not empty.
- Can not delete root path
- Can not delete the directory: [%s], as it is not empty and o
- {path}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/d5db0c665d3a44e3.
Report an issue: GitHub.