{"record":{"id":"17f183e3e0c259cc","repo":"apache/cassandra","slug":"cannot-delete-the-directory-as-it-is-not-empty","errorCode":null,"errorMessage":"Cannot delete the directory {} as it is not empty. (Content: {})","messagePattern":"Cannot delete the directory (.+?) as it is not empty\\. \\(Content: (.+?)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/io/util/FileUtils.java","lineNumber":740,"sourceCode":"     *\n     * @param path the path to the directory\n     */\n    public static void deleteDirectoryIfEmpty(Path path) throws IOException\n    {\n        Preconditions.checkArgument(Files.isDirectory(path), String.format(\"%s is not a directory\", path));\n\n        try\n        {\n            logger.info(\"Deleting directory {}\", path);\n            Files.delete(path);\n        }\n        catch (DirectoryNotEmptyException e)\n        {\n            try (Stream<Path> paths = Files.list(path))\n            {\n                String content = paths.map(p -> p.getFileName().toString()).collect(Collectors.joining(\", \"));\n\n                logger.warn(\"Cannot delete the directory {} as it is not empty. (Content: {})\", path, content);\n            }\n        }\n    }\n\n    public static boolean isDirectIOSupported(File file)\n    {\n        File testFile = null;\n        try\n        {\n            File dir = file.isDirectory() ? file : file.parent();\n            testFile = createTempFile(\"direct-io-test\", \".tmp\", dir);\n\n            // Direct IO requires knowing the block size for buffer alignment\n            if (blockSize(testFile) <= 0)\n                return false;\n\n            try (FileChannel channel = FileChannel.open(testFile.toPath(),\n                                                        StandardOpenOption.READ,","sourceCodeStart":722,"sourceCodeEnd":758,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/util/FileUtils.java#L722-L758","documentation":"After a recursive move, FileUtils.deleteDirectoryIfEmpty tries to delete the now-empty source directory; if the OS reports DirectoryNotEmptyException it logs a warning listing the directory's contents and leaves it in place.","triggerScenarios":"moveRecursively finished moving files but new files appeared in the source directory mid-move (concurrent writers), so the directory is no longer empty at deletion time.","commonSituations":"Concurrent compaction or flush writing new sstables into the source directory while it is being moved; interrupted prior moves leaving stray files.","solutions":["Investigate what is still writing to the source directory and stop it before moving","Re-run the move or manually delete the directory once it is genuinely empty","Check for orphaned files (e.g. partial sstables) left behind and clean them with the appropriate tooling","Avoid moving live data directories; quiesce writes first"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"try (Stream<Path> remaining = Files.list(sourceDir)) {\n    if (remaining.findAny().isPresent()) {\n        // directory still in use; abort or defer the move\n    }\n}","typeGuard":"boolean isEmptyDir(Path p) throws IOException { try (Stream<Path> s = Files.list(p)) { return s.findAny().isEmpty(); } }","tryCatchPattern":"try {\n    FileUtils.moveRecursively(source, target);\n} catch (DirectoryNotEmptyException e) {\n    // stop writers to source, clean leftovers, delete manually\n}","preventionTips":["Quiesce writes to the source directory before moving it","Move only quiesced/offline data directories","Check for concurrent compaction/flush activity first","Clean orphaned files before retrying moves"],"tags":["io","filesystem","delete","concurrency"],"backgroundTag":"directory-not-empty","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}