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

  1. Delete the siblings individually and skip the protected subtree (delete contents of the protected descendant separately or leave it)
  2. Empty the protected descendant so the non-empty condition no longer holds
  3. 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

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


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/630eb2acb7c64f95. Report an issue: GitHub.