{"record":{"id":"9ef148403fbc0153","repo":"apache/flink","slug":"directory-is-not-a-directory-but-a-regular-file","errorCode":null,"errorMessage":"{directory} is not a directory but a regular file","messagePattern":"(.+?) is not a directory but a regular file","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/util/FileUtils.java","lineNumber":367,"sourceCode":"            final File[] files = directory.listFiles();\n\n            if (files == null) {\n                // directory does not exist any more or no permissions\n                if (directory.exists()) {\n                    throw new IOException(\"Failed to list contents of \" + directory);\n                } else {\n                    throw new FileNotFoundException(directory.toString());\n                }\n            }\n\n            // remove all files in the directory\n            for (File file : files) {\n                if (file != null) {\n                    deleteFileOrDirectory(file);\n                }\n            }\n        } else if (directory.exists()) {\n            throw new IOException(directory + \" is not a directory but a regular file\");\n        } else {\n            // else does not exist at all\n            throw new FileNotFoundException(directory.toString());\n        }\n    }\n\n    private static void guardIfNotThreadSafe(ThrowingConsumer<File, IOException> toRun, File file)\n            throws IOException {\n        if (OperatingSystem.isWindows()) {\n            guardIfWindows(toRun, file);\n            return;\n        }\n        if (OperatingSystem.isMac()) {\n            guardIfMac(toRun, file);\n            return;\n        }\n\n        toRun.accept(file);","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/util/FileUtils.java#L349-L385","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nFileUtils.cleanDirectory(new File(path)); // path is a regular file\n\n// after\nFile f = new File(path);\nif (f.exists() && !f.isDirectory()) {\n    throw new IllegalStateException(\"Expected directory but found file at \" + path\n        + \" - check configuration\");\n}\nFileUtils.cleanDirectory(f);","handlingStrategy":"type-guard","validationCode":"File d = new File(path);\nif (d.exists() && !d.isDirectory()) {\n    throw new IllegalStateException(\"Path is a file, expected directory: \" + path);\n}","typeGuard":"static boolean isCleanableDirectory(File f) { return !f.exists() || Files.isDirectory(f.toPath()); } // note: symlink-to-dir is skipped by cleanDirectory itself","tryCatchPattern":"catch (IOException e) and surface the misconfigured path to the operator; this is a configuration/state bug, not transient.","preventionTips":["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"],"tags":["flink-core","filesystem","cleanup","validation","configuration"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}