apache/hadoop · error · PathIsNotEmptyDirectoryException
iip.getPath() + " is non empty"
Error message
iip.getPath() + " is non empty"
What it means
FSDirDeleteOp.delete checks isNonEmptyDirectory(iip) and, when the delete is non-recursive (recursive=false from FileSystem.delete(path, false) or 'hdfs dfs -rm' without -r), throws PathIsNotEmptyDirectoryException. HDFS deliberately refuses to silently discard a populated directory: a non-recursive delete only removes empty directories and files named exactly by the path. If recursive=true is passed, the same directory deletes fine (after a protected-descendants check).
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirDeleteOp.java:111
* @throws IOException
*/
static BlocksMapUpdateInfo delete(
FSNamesystem fsn, FSPermissionChecker pc, String src, boolean recursive,
boolean logRetryCache) throws IOException {
FSDirectory fsd = fsn.getFSDirectory();
if (FSDirectory.isExactReservedName(src)) {
throw new InvalidPathException(src);
}
final INodesInPath iip = fsd.resolvePath(pc, src, DirOp.WRITE_LINK);
if (fsd.isPermissionEnabled()) {
fsd.checkPermission(pc, iip, false, null, FsAction.WRITE, null,
FsAction.ALL, true);
}
if (fsd.isNonEmptyDirectory(iip)) {
if (!recursive) {
throw new PathIsNotEmptyDirectoryException(
iip.getPath() + " is non empty");
}
DFSUtil.checkProtectedDescendants(fsd, iip);
}
return deleteInternal(fsn, iip, logRetryCache);
}
/**
* Delete a path from the name space
* Update the count at each ancestor directory with quota
* <br>
* Note: This is to be used by
* {@link org.apache.hadoop.hdfs.server.namenode.FSEditLog} only.
* <br>
*
* @param fsd the FSDirectory instance
* @param iip inodes of a path to be deletedView on GitHub (pinned to 2add963021)
Solutions
- If the intent is to remove everything, pass recursive=true: fs.delete(dir, true).
- If the intent is 'delete only when empty', keep recursive=false and catch PathIsNotEmptyDirectoryException as the expected signal (via RemoteException.unwrap / checking the exception class name).
- Alternatively list the directory first and decide: fs.listStatus(dir).length == 0 before deleting non-recursively.
Example fix
// before
fs.delete(dir, false); // throws if dir has children
// after
boolean removed;
if (fs.getFileStatus(dir).isDirectory() && fs.listStatus(dir).length > 0) {
removed = fs.delete(dir, true); // deliberate recursive delete
} else {
removed = fs.delete(dir, false);
} Defensive patterns
Strategy: validation
Validate before calling
boolean empty = fs.getFileStatus(dir).isDirectory()
? fs.listStatus(dir).length == 0 : true;
boolean removed = fs.delete(dir, /*recursive=*/ !empty); Try / catch
try {
fs.delete(dir, false);
} catch (PathIsNotEmptyDirectoryException e) {
// only thrown client-side as RemoteException; unwrap first:
// IOException ioe = RemoteExceptionHandler.decode(...) (catch IOException, check className)
// deliberate: directory was populated between check and delete
fs.delete(dir, true);
} Prevention
- Decide recursion policy explicitly per call site; do not copy fs.delete(dir, false) from local-FS habits.
- For 'delete only if empty' semantics, check listStatus(...).length == 0 first and treat the exception as expected.
- In shell scripts, use hdfs dfs -rm -r for intentional recursive deletes; plain -rm fails on populated dirs.
When it happens
Trigger: fs.delete(dirPath, false) where dirPath contains children; 'hdfs dfs -rm /some/dir' (without -r or -R) on a populated directory.
Common situations: Code ported from java.io.File.delete() or POSIX unlink() semantics where an explicit non-recursive delete is used as a safety guard; cleanup scripts that expect dirs to already be empty; tooling that intends 'delete only if empty' but does not handle the exception.
Related errors
- Can not delete the directory: [%s], as it is not empty and o
- Cannot delete a non-empty directory. : %s
- {path}
- {path}
- Directory " + f.toString() + " is not empty
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/4a8a39e6a62500c7.
Report an issue: GitHub.