{"record":{"id":"52488e0339194d26","repo":"octobercms/october","slug":"editor-lang-filesystem-error-deleting-dir-not-emp","errorCode":null,"errorMessage":"editor::lang.filesystem.error_deleting_dir_not_empty","messagePattern":"editor::lang\\.filesystem\\.error_deleting_dir_not_empty","errorType":"validation","errorClass":"ApplicationException","httpStatus":null,"severity":"warning","filePath":"modules/editor/traits/FileSystemFunctions.php","lineNumber":141,"sourceCode":"        foreach ($fileList as $path) {\n            if (!$this->validateFileSystemPath($path)) {\n                throw new ApplicationException(Lang::get('editor::lang.filesystem.invalid_path'));\n            }\n\n            $fullPath = $basePath.'/'.$path;\n            if (File::exists($fullPath)) {\n                if (!File::isDirectory($fullPath)) {\n                    if (!@File::delete($fullPath)) {\n                        throw new ApplicationException(Lang::get(\n                            'editor::lang.filesystem.error_deleting_file',\n                            ['name' => $path]\n                        ));\n                    }\n                }\n                else {\n                    $empty = File::isDirectoryEmpty($fullPath);\n                    if (!$empty) {\n                        throw new ApplicationException(Lang::get(\n                            'editor::lang.filesystem.error_deleting_dir_not_empty',\n                            ['name' => $path]\n                        ));\n                    }\n\n                    if (!@rmdir($fullPath)) {\n                        throw new ApplicationException(Lang::get(\n                            'editor::lang.filesystem.error_deleting_dir',\n                            ['name' => $path]\n                        ));\n                    }\n                }\n            }\n        }\n    }\n\n    /**\n     * editorMoveFilesOrDirectories","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/editor/traits/FileSystemFunctions.php#L123-L159","documentation":"Thrown by editorDeleteFileOrDirectory when a selected path is an existing directory that is NOT empty (File::isDirectoryEmpty returns false, lines 138-145). By design the delete command only removes empty directories — there is no recursive delete. The usort by strlen descending deletes leaves first, so a multi-select containing a parent AND all its children works, but any unselected child aborts with 'Error deleting directory :name. The directory is not empty.'.","triggerScenarios":"command_onAssetDelete where 'files' includes a directory but not every entry inside it (the sidebar selection missed nested or hidden files), or a file was created inside the directory between selection and the request. Because processing is longest-path-first, a missed child typically fails the parent AFTER some children were already deleted.","commonSituations":"Selecting a folder node without expanding/selecting its contents in the tree; dotfiles (.gitkeep, .DS_Store) not shown in the sidebar but counted by isDirectoryEmpty; concurrent uploads/builds writing into the directory during the delete.","solutions":["Expand the directory in the sidebar and select ALL of its contents together with the directory itself (the strlen sort then removes children first)","Empty the directory first (delete its files), then delete the directory in a second step","Refresh the tree and retry if another session may have written files meanwhile","Remove invisible leftovers on disk (rm -rf themes/<theme>/assets/<dir>) when the sidebar cannot see them"],"exampleFix":"// before\nfiles = ['js/lib']                    // contains jquery.js -> blocked\n// after\nfiles = ['js/lib/jquery.js', 'js/lib'] // child first, parent then empties","handlingStrategy":"validation","validationCode":"foreach ($files as $path) {\n    $full = $assetsBase.'/'.$path;\n    if (is_dir($full) && !(new \\FilesystemIterator($full))->valid()) {\n        // directory has entries: include them in $files or empty it first\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include ALL children (recursively) in the delete selection alongside the folder","Remember the API deletes empty directories only — there is no recursive delete","Refresh before deleting if build tools may have written files into the folder"],"tags":["filesystem","directory-not-empty","validation","editor","winter-cms"],"backgroundTag":"directory-not-empty","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}