apache/flink · error · IOException
{directory} is not a directory
Error message
{directory} is not a directory What it means
Thrown by FileUtils.deleteDirectory when the given path exists but is a regular file. deleteDirectory is only meaningful for directories; deleting a file at that path would exceed the caller's intent, so it fails fast instead of guessing.
Source
Thrown at flink-core/src/main/java/org/apache/flink/util/FileUtils.java:338
// directory exists and is a directory
// empty the directory first
try {
cleanDirectoryInternal(directory);
} catch (FileNotFoundException ignored) {
// someone concurrently deleted the directory, nothing to do for us
return;
}
// delete the directory. this fails if the directory is not empty, meaning
// if new files got concurrently created. we want to fail then.
// if someone else deleted the empty directory concurrently, we don't mind
// the result is the same for us, after all
Files.deleteIfExists(directory.toPath());
} else if (directory.exists()) {
// exists but is file, not directory
// either an error from the caller, or concurrently a file got created
throw new IOException(directory + " is not a directory");
}
// else: does not exist, which is okay (as if deleted)
}
private static void cleanDirectoryInternal(File directory) throws IOException {
if (Files.isSymbolicLink(directory.toPath())) {
// the user directories which symbolic links point to should not be cleaned.
return;
}
if (directory.isDirectory()) {
final File[] files = directory.listFiles();
if (files == null) {
// directory does not exist any more or no permissions
if (directory.exists()) {
throw new IOException("Failed to list contents of " + directory);
} else {
throw new FileNotFoundException(directory.toString());View on GitHub (pinned to 2f3c205e92)
Solutions
- Check whether the path should really be a directory; if it may be either, use deleteFileOrDirectory instead
- Remove the stale file manually or via a pre-clean step, then rerun
- Investigate what created a file where a directory was expected — that is usually the actual bug
Example fix
// before
FileUtils.deleteDirectory(new File(path)); // path is a file
// after
File f = new File(path);
if (f.isDirectory()) {
FileUtils.deleteDirectory(f);
} else if (f.exists()) {
// deliberate: only files ever expected here
org.apache.flink.util.Preconditions.checkState(!f.isDirectory(), path);
f.delete();
} Defensive patterns
Strategy: type-guard
Validate before calling
File f = new File(path);
if (f.exists() && !f.isDirectory()) {
throw new IOException("Expected directory, found file: " + f);
} Type guard
static boolean isDeletableDirectory(File f) { return !f.exists() || f.isDirectory(); } Try / catch
catch (IOException e) when cleaning best-effort: log and continue if cleanup is non-critical.
Prevention
- Use deleteFileOrDirectory when the path's type is genuinely unknown
- Investigate anything creating a file where your code expects a directory — that is the real defect
When it happens
Trigger: Calling FileUtils.deleteDirectory(file) where file exists and isFile() is true; a typical case is a path that used to be a directory but a concurrent process recreated it as a file, or the caller mixed up deleteFileOrDirectory and deleteDirectory.
Common situations: Cleanup code assuming a workspace path is always a directory; races where another process replaced the directory with a symlink target/file; tests pointing cleanup at a file artifact by mistake.
Related errors
- {directory} is not a directory but a regular file
- There are no legal characters in the file name
- Failed to list contents of {directory}
- {directory}
- DistributedCache supports only local files for Collection En
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/0d16c18889c33f2f.
Report an issue: GitHub.