{"record":{"id":"41bfe6362539dc92","repo":"octobercms/october","slug":"editor-lang-filesystem-error-deleting-dir","errorCode":null,"errorMessage":"editor::lang.filesystem.error_deleting_dir","messagePattern":"editor::lang\\.filesystem\\.error_deleting_dir","errorType":"exception","errorClass":"ApplicationException","httpStatus":null,"severity":"error","filePath":"modules/editor/traits/FileSystemFunctions.php","lineNumber":148,"sourceCode":"                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\n     */\n    protected function editorMoveFilesOrDirectories($basePath, $selectedList, $destinationDir)\n    {\n        if (!count($selectedList)) {\n            throw new ApplicationException(Lang::get('editor::lang.filesystem.selected_files_not_found'));\n        }\n","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/editor/traits/FileSystemFunctions.php#L130-L166","documentation":"Thrown by editorDeleteFileOrDirectory when @rmdir() fails on a directory that was just confirmed empty (lines 147-152). Message: 'Error deleting directory :name.'. An empty directory whose removal fails means the PHP user lacks write permission on the directory's PARENT (removing a dir modifies the parent's entry), or a race where something recreated a file between the isDirectoryEmpty check and rmdir.","triggerScenarios":"command_onAssetDelete on an empty dir under themes/<theme>/assets when the parent directory is root-owned or not writable by the webserver user; SELinux denying rmdir; a background process (build, watcher) recreating files inside the directory at the moment of deletion.","commonSituations":"Assets directory tree created by root deploys but served/edited by www-data; platform permission drift after moving a project between users; dev watchers (webpack --watch, vite) continuously writing output into asset folders.","solutions":["Make the PARENT directory writable by the PHP user (chown/chmod the folder that contains the directory being deleted)","Stop build watchers or other writers, refresh, and retry the delete","Check SELinux/AppArmor if standard permissions look fine","Retry once after a refresh — the emptiness check may have raced a transient file"],"exampleFix":"# before: parent owned by root\n$ sudo chown -R www-data:www-data themes/demo/assets\n# then retry the delete in the Editor","handlingStrategy":"try-catch","validationCode":"$full = $assetsBase.'/'.$path;\nif (is_dir($full) && !is_writable(dirname($full))) {\n    // rmdir needs write on the PARENT directory — fix it first\n}","typeGuard":null,"tryCatchPattern":"try {\n    if (!@rmdir($fullPath)) {\n        throw new ApplicationException(Lang::get('editor::lang.filesystem.error_deleting_dir', ['name' => $path]));\n    }\n} catch (ApplicationException $e) {\n    // possible race: re-check emptiness and retry once\n    clearstatcache(true, $fullPath);\n    if (!is_dir($fullPath)) { return; } // someone else removed it\n    throw $e;\n}","preventionTips":["Keep parent directories writable by the webserver user","Stop file watchers before bulk-deleting asset folders","Retry once after a refresh — a writer may have raced the emptiness check"],"tags":["filesystem","permissions","io","editor","winter-cms"],"backgroundTag":"filesystem-permission-denied","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}