apache/hadoop · error · PathIsNotEmptyDirectoryException
{path}
Error message
{path} What it means
For directory deletes, the code checks whether the directory prefix has any contents; delete(f, recursive=false) on a non-empty directory throws Hadoop's PathIsNotEmptyDirectoryException with the path string as the message. The bucket root is refused separately by rejectRootDirectoryDelete, and an empty directory marker is deleted as a single object.
Source
Thrown at hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSObjectBucketUtils.java:260
String key = OBSCommonUtils.pathToKey(owner, f);
if (status.isDirectory()) {
LOG.debug("delete: Path is a directory: {} - recursive {}", f,
recursive);
key = OBSCommonUtils.maybeAddTrailingSlash(key);
if (!key.endsWith("/")) {
key = key + "/";
}
boolean isEmptyDir = OBSCommonUtils.isFolderEmpty(owner, key);
if (key.equals("/")) {
return OBSCommonUtils.rejectRootDirectoryDelete(
owner.getBucket(), isEmptyDir, recursive);
}
if (!recursive && !isEmptyDir) {
throw new PathIsNotEmptyDirectoryException(f.toString());
}
if (isEmptyDir) {
LOG.debug(
"delete: Deleting fake empty directory {} - recursive {}",
f, recursive);
OBSCommonUtils.deleteObject(owner, key);
} else {
LOG.debug(
"delete: Deleting objects for directory prefix {} "
+ "- recursive {}",
f, recursive);
deleteNonEmptyDir(owner, recursive, key);
}
} else {
LOG.debug("delete: Path is a file");
OBSCommonUtils.deleteObject(owner, key);View on GitHub (pinned to 2add963021)
Solutions
- Pass recursive=true when the whole tree should be removed: fs.delete(dir, true)
- List and delete children explicitly when only some entries should go
- On a suspected race, catch the exception, re-list, and retry once
Example fix
// before fs.delete(dir, false); // after fs.delete(dir, true);
Defensive patterns
Strategy: validation
Validate before calling
if (fs.getFileStatus(dir).isDirectory()) {
boolean empty = !fs.listStatus(dir).iterator().hasNext()
&& fs.listStatus(dir).length == 0;
if (!empty) {
// pass recursive=true, or delete children selectively
}
} Type guard
static boolean isEmptyDirectory(FileSystem fs, Path p) throws IOException {
return fs.getFileStatus(p).isDirectory() && fs.listStatus(p).length == 0;
} Try / catch
try {
fs.delete(dir, false);
} catch (PathIsNotEmptyDirectoryException e) {
// content appeared between check and delete: list again and decide,
// or escalate to fs.delete(dir, true) if full removal is intended
} Prevention
- Default to recursive=true when the whole tree should go
- Use listStatus-based selective deletes for partial cleanup
- Re-check emptiness right before non-recursive deletes in concurrent environments
When it happens
Trigger: fs.delete(dir, false) when dir contains objects or subdirectory markers; cleanup code written for a POSIX filesystem where false was thought sufficient; dropping a partition directory without the recursive flag.
Common situations: Porting local-filesystem utilities to object storage where 'directory' means a prefix with keys; a race where another writer adds an object between the emptiness check and the delete call; Hive/Spark partition drop configured non-recursive.
Related errors
- {path}
- Can not delete the directory: [%s], as it is not empty and o
- Directory " + f.toString() + " is not empty
- Directory {} is not empty.
- Can not delete root path
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/95a06f2e76cbc72f.
Report an issue: GitHub.