apache/hadoop · error · AccessControlException
Cannot delete/rename non-empty protected subdirectory {}
Error message
Cannot delete/rename non-empty protected subdirectory {} What it means
Companion check to the protected-directory rule: DFSUtil.checkProtectedDescendants walks the protected set for descendants of the path being deleted (protectedDirs.subSet(src + '/', src + '0')). If any protected descendant is a non-empty directory, the delete/rename of its ancestor is refused with AccessControlException naming the descendant.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSUtil.java:1909
}
String src = iip.getPath();
// Is src protected? Caller has already checked it is non-empty.
if (protectedDirs.contains(src)) {
throw new AccessControlException(
"Cannot delete/rename non-empty protected directory " + src);
}
// Are any descendants of src protected?
// The subSet call returns only the descendants of src since
// {@link Path#SEPARATOR} is "/" and '0' is the next ASCII
// character after '/'.
for (String descendant :
protectedDirs.subSet(src + Path.SEPARATOR, src + "0")) {
INodesInPath subdirIIP =
fsd.getINodesInPath(descendant, FSDirectory.DirOp.WRITE);
if (fsd.isNonEmptyDirectory(subdirIIP)) {
throw new AccessControlException(
"Cannot delete/rename non-empty protected subdirectory "
+ descendant);
}
}
if (fsd.isProtectedSubDirectoriesEnable()) {
while (!src.isEmpty()) {
int index = src.lastIndexOf(Path.SEPARATOR_CHAR);
src = src.substring(0, index);
if (protectedDirs.contains(src)) {
throw new AccessControlException(
"Cannot delete/rename subdirectory under protected subdirectory "
+ src);
}
}
}
}
View on GitHub (pinned to 2add963021)
Solutions
- Delete the siblings individually and skip the protected subtree (delete contents of the protected descendant separately or leave it)
- Empty the protected descendant so the non-empty condition no longer holds
- Have the admin drop that descendant from fs.protected.directories if the operation is truly intended
Example fix
// before hdfs dfs -rm -r /data // /data/warehouse protected and non-empty -> error // after: delete around the protected subtree hdfs dfs -rm /data/tmp/* hdfs dfs -rm /data/raw/* // leave /data/warehouse in place
Defensive patterns
Strategy: try-catch
Try / catch
try {
fs.delete(parentPath, true);
} catch (AccessControlException e) {
if (e.getMessage() != null && e.getMessage().contains("protected subdirectory")) {
// a protected descendant under parentPath is non-empty: fall back to
// listing children and deleting each non-protected one individually
} else {
throw e;
}
} Prevention
- Before rm -r of large trees, cross-check the tree against the published protected-directories list
- Implement recursive delete as per-child operations so one protected subtree does not abort the whole cleanup
When it happens
Trigger: Recursively deleting or renaming a parent directory when some deeper subdirectory is listed in fs.protected.directories and is non-empty, e.g. rm -r /data while /data/warehouse is protected.
Common situations: Broad cleanup jobs (rm -r /data) colliding with fine-grained protected paths configured underneath; protected zones nested inside temp trees.
Related errors
- Cannot delete/rename non-empty protected directory {}
- Cannot delete/rename subdirectory under protected subdirecto
- Destination '{destFile}' exists but cannot be deleted
- Failed to delete {dir}
- Directory {dir} is in an inconsistent state: storage directo
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/630eb2acb7c64f95.
Report an issue: GitHub.