apache/hadoop · error · IOException
Cannot remove directory {f}: It is not empty!
Error message
Cannot remove directory {f}: It is not empty! What it means
Thrown by AliyunOSSFileSystem.delete(): the target is a directory, recursive=false, and listStatus() on it returned one or more entries. Object stores cannot atomically delete a 'directory' with children in non-recursive mode, so the connector refuses with IOException("Cannot remove directory " + f + ": It is not empty!") to emulate POSIX rm semantics.
Source
Thrown at hadoop-tools/hadoop-aliyun/src/main/java/org/apache/hadoop/fs/aliyun/oss/AliyunOSSFileSystem.java:212
private boolean innerDelete(FileStatus status, boolean recursive)
throws IOException {
Path f = status.getPath();
String p = f.toUri().getPath();
FileStatus[] statuses;
// indicating root directory "/".
if (p.equals("/")) {
statuses = listStatus(status.getPath());
boolean isEmptyDir = statuses.length <= 0;
return rejectRootDirectoryDelete(isEmptyDir, recursive);
}
String key = pathToKey(f);
if (status.isDirectory()) {
if (!recursive) {
// Check whether it is an empty directory or not
statuses = listStatus(status.getPath());
if (statuses.length > 0) {
throw new IOException("Cannot remove directory " + f +
": It is not empty!");
} else {
// Delete empty directory without '-r'
key = AliyunOSSUtils.maybeAddTrailingSlash(key);
store.deleteObject(key);
}
} else {
store.deleteDirs(key);
}
} else {
store.deleteObject(key);
}
createFakeDirectoryIfNecessary(f);
return true;
}
/**View on GitHub (pinned to 2add963021)
Solutions
- Pass recursive=true when the intent is to delete the whole subtree: fs.delete(path, true)
- If it must be empty, list the children first and delete/move them, then delete the directory key
- Check for non-obvious child keys (including zero-byte directory markers) with listStatus before assuming emptiness
Example fix
// before fs.delete(dirPath, /*recursive*/ false); // after fs.delete(dirPath, /*recursive*/ true);
Defensive patterns
Strategy: validation
Validate before calling
FileStatus st = fs.getFileStatus(dir);
if (st.isDirectory() && fs.listStatus(dir).length > 0) {
boolean recursive = /* user intent */ true;
if (!recursive) throw new IOException("Directory not empty: " + dir);
}
fs.delete(dir, recursive); Try / catch
catch (IOException e) { if (e.getMessage().startsWith("Cannot remove directory")) { /* escalate to delete(path, true) or delete children manually */ } throw e; } Prevention
- Always pass the recursive flag explicitly instead of defaulting to false for directories
- Before 'empty-dir' deletes, list children to catch hidden marker/_SUCCESS objects
When it happens
Trigger: Calling fs.delete(path, false) on an OSS prefix that contains objects or child prefixes; shell 'hadoop fs -rm oss://bucket/dir' (non-recursive default) where dir has children.
Common situations: Cleanup scripts ported from HDFS that used rm without -r on directories; assuming an empty directory exists when OSS still holds a zero-byte marker or hidden child keys (e.g., _SUCCESS, .crc files, or 'fake directory' markers from other tools).
Related errors
- Cannot delete root path
- Can not delete the directory: [%s], as it is not empty and o
- Cannot delete a non-empty directory. : %s
- {path}
- {path}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/d441491407362082.
Report an issue: GitHub.