apache/hadoop · error · IOException
Directory: {file} is not empty.
Error message
Directory: {file} is not empty. What it means
delete(path, recursive=false) lists the directory first; if it contains any entries and recursion is off, deletion is refused with this IOException rather than silently dropping content. Only delete(path, true) walks and removes children.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java:432
* the overhead of opening/closing a TCP connection.
*/
private boolean delete(FTPClient client, Path file, boolean recursive)
throws IOException {
Path workDir = new Path(client.printWorkingDirectory());
Path absolute = makeAbsolute(workDir, file);
String pathName = absolute.toUri().getPath();
try {
FileStatus fileStat = getFileStatus(client, absolute);
if (fileStat.isFile()) {
return client.deleteFile(pathName);
}
} catch (FileNotFoundException e) {
//the file is not there
return false;
}
FileStatus[] dirEntries = listStatus(client, absolute);
if (dirEntries != null && dirEntries.length > 0 && !(recursive)) {
throw new IOException("Directory: " + file + " is not empty.");
}
for (FileStatus dirEntry : dirEntries) {
delete(client, new Path(absolute, dirEntry.getPath()), recursive);
}
return client.removeDirectory(pathName);
}
@VisibleForTesting
FsAction getFsAction(int accessGroup, FTPFile ftpFile) {
FsAction action = FsAction.NONE;
if (ftpFile.hasPermission(accessGroup, FTPFile.READ_PERMISSION)) {
action = action.or(FsAction.READ);
}
if (ftpFile.hasPermission(accessGroup, FTPFile.WRITE_PERMISSION)) {
action = action.or(FsAction.WRITE);
}
if (ftpFile.hasPermission(accessGroup, FTPFile.EXECUTE_PERMISSION)) {
action = action.or(FsAction.EXECUTE);View on GitHub (pinned to 2add963021)
Solutions
- Call fs.delete(path, true) when recursive deletion is intended
- If only empty directories should be removed, check fs.listStatus(dir).length == 0 first and skip otherwise
- List the directory to see what entries exist — dotfiles count as entries
Example fix
// before
fs.delete(dir, false); // IOException: Directory: ... is not empty.
// after
if (fs.getFileStatus(dir).isDirectory() && fs.listStatus(dir).length > 0) {
boolean ok = fs.delete(dir, true); // recursive delete intended
} else {
fs.delete(dir, false);
} Defensive patterns
Strategy: validation
Validate before calling
if (fs.getFileStatus(dir).isDirectory() && fs.listStatus(dir).length > 0) {
boolean removed = fs.delete(dir, true); // explicit recursive decision
} else {
fs.delete(dir, false);
} Type guard
static boolean isEmptyDirectory(FileSystem fs, Path p) throws IOException {
FileStatus st = fs.getFileStatus(p);
return st.isDirectory() && fs.listStatus(p).length == 0;
} Try / catch
try {
fs.delete(dir, false);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("not empty")) {
fs.delete(dir, true); // only if recursive delete is acceptable
} else {
throw e;
}
} Prevention
- Pass recursive=true deliberately when bulk deletion is intended
- Before deleting 'empty' dirs, listStatus them — hidden dotfiles still count as entries
When it happens
Trigger: fs.delete(dir, false) on a non-empty FTP directory; cleanup code assuming the directory is empty; hidden entries (dotfiles, subdirectories) making a directory look empty to the user.
Common situations: Job cleanup expecting an empty output dir; FTP servers that list hidden files; shared upload directories that accumulate entries between runs.
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/62b358436bc90cf5.
Report an issue: GitHub.