apache/flink · error · IOException
{directory} is not a directory but a regular file
Error message
{directory} is not a directory but a regular file What it means
Thrown from cleanDirectoryInternal when the path exists but is a regular file. Cleaning operates on directory contents; a file at the path has no 'contents' to clean, so the operation refuses rather than deleting something the caller did not describe.
Source
Thrown at flink-core/src/main/java/org/apache/flink/util/FileUtils.java:367
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());
}
}
// remove all files in the directory
for (File file : files) {
if (file != null) {
deleteFileOrDirectory(file);
}
}
} else if (directory.exists()) {
throw new IOException(directory + " is not a directory but a regular file");
} else {
// else does not exist at all
throw new FileNotFoundException(directory.toString());
}
}
private static void guardIfNotThreadSafe(ThrowingConsumer<File, IOException> toRun, File file)
throws IOException {
if (OperatingSystem.isWindows()) {
guardIfWindows(toRun, file);
return;
}
if (OperatingSystem.isMac()) {
guardIfMac(toRun, file);
return;
}
toRun.accept(file);View on GitHub (pinned to 2f3c205e92)
Solutions
- Inspect the path — decide whether it should be deleted as a file or the config should point elsewhere
- Delete the offending file and recreate the directory before rerunning cleanup
- Validate configuration paths at startup (expectDirectory) so mistakes surface early with context
Example fix
// before
FileUtils.cleanDirectory(new File(path)); // path is a regular file
// after
File f = new File(path);
if (f.exists() && !f.isDirectory()) {
throw new IllegalStateException("Expected directory but found file at " + path
+ " - check configuration");
}
FileUtils.cleanDirectory(f); Defensive patterns
Strategy: type-guard
Validate before calling
File d = new File(path);
if (d.exists() && !d.isDirectory()) {
throw new IllegalStateException("Path is a file, expected directory: " + path);
} Type guard
static boolean isCleanableDirectory(File f) { return !f.exists() || Files.isDirectory(f.toPath()); } // note: symlink-to-dir is skipped by cleanDirectory itself Try / catch
catch (IOException e) and surface the misconfigured path to the operator; this is a configuration/state bug, not transient.
Prevention
- Validate configured directory paths at component startup with clear errors
- Keep data, temp, and cache directories distinct so a stray file cannot squat on a directory path
When it happens
Trigger: Calling FileUtils.cleanDirectory on a path that is a file — e.g. a leftover archive recreated at the directory's location, or a symlink-to-file resolved to a non-directory (note: symlinked directories return early instead).
Common situations: State store / cache dir replaced by a file after a misconfigured run; path configuration pointing at a file (wrong key, trailing filename); remnants of previous experiments in temp dirs.
Related errors
- {directory} is not a directory
- Value for config option %s must be one of %s (was %s)
- Can not create a Path from an empty string
- tempDirectories contains null entries
- Segment size must be a power of 2!
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/9ef148403fbc0153.
Report an issue: GitHub.