octobercms/october · error · ApplicationException
editor::lang.filesystem.error_deleting_directory
Error message
editor::lang.filesystem.error_deleting_directory
What it means
Thrown by editorMoveFilesOrDirectories after a directory's copyDirectory() SUCCEEDED but the original path contains '../', so the code refuses to delete the source (lines 224-229). Message: 'Error deleting the original directory :dir'. This is defense-in-depth: every source already passed validateFileSystemPath (which rejects '..'), so it is only reachable when $basePath itself was built with '../' segments — i.e., a custom extension supplying an unnormalized base path. Note the consequence: content now exists in BOTH places because the copy already ran.
Source
Thrown at modules/editor/traits/FileSystemFunctions.php:225
if (is_file($originalFullPath)) {
if (!@File::move($originalFullPath, $newFullPath)) {
throw new ApplicationException(Lang::get(
'editor::lang.filesystem.error_moving_file',
['file' => $basename]
));
}
}
elseif (is_dir($originalFullPath)) {
if (!@File::copyDirectory($originalFullPath, $newFullPath)) {
throw new ApplicationException(Lang::get(
'editor::lang.filesystem.error_moving_directory',
['dir' => $basename]
));
}
if (strpos($originalFullPath, '../') !== false) {
throw new ApplicationException(Lang::get(
'editor::lang.filesystem.error_deleting_directory',
['dir' => $basename]
));
}
if (strpos($originalFullPath, $safeDir) !== 0) {
throw new ApplicationException(Lang::get(
'editor::lang.filesystem.error_deleting_directory',
['dir' => $basename]
));
}
if (!@File::deleteDirectory($originalFullPath)) {
throw new ApplicationException(Lang::get(
'editor::lang.filesystem.error_deleting_directory',
['dir' => $basename]
));
}View on GitHub (pinned to b608633a7e)
Solutions
- Normalize the base path before calling editorMoveFilesOrDirectories: $basePath = realpath($basePath)
- If already hit, the destination copy is complete — delete the original directory manually after verifying the copy
- Audit custom editor extensions for '..' in their resolved base paths
- Prefer an absolute, symlink-free base path (or a symlink) instead of relative traversal segments
Example fix
// before (custom extension) $base = base_path().'/../shared/assets'; // '..' leaks into originalFullPath $this->editorMoveFilesOrDirectories($base, $src, $dst); // after $base = realpath(base_path().'/../shared/assets'); // normalized, no '../'
Defensive patterns
Strategy: validation
Validate before calling
// In custom extensions, before calling editorMoveFilesOrDirectories
$basePath = realpath($basePath);
if ($basePath === false || strpos($basePath, '../') !== false) {
throw new \UnexpectedValueException('Base path must be a normalized absolute directory');
} Prevention
- Always realpath() the base path in custom editor extensions
- Never compose asset roots with '..' segments — use absolute paths or symlinks
- If hit, the copy succeeded: verify the destination then remove the original manually
When it happens
Trigger: A custom Editor\Classes\ExtensionBase subclass whose getAssetsPath() (or equivalent) returns a path containing '..' (e.g. base_path().'/../shared/assets'), combined with command_onAssetMove of a directory. Standard CMS/Tailor extensions, whose base paths are normalized theme directories, cannot trigger it.
Common situations: Bespoke editor extensions mounting asset roots outside the theme via relative '..' paths; refactors that assemble base paths from config without realpath(); copied example code for Tailor content extensions with sloppy path joins.
Related errors
- editor::lang.filesystem.invalid_path
- editor::lang.filesystem.original_not_found
- editor::lang.filesystem.type_not_allowed
- editor::lang.filesystem.error_renaming
- editor::lang.filesystem.error_deleting_file
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/e3ee4a3a8359e123.
Report an issue: GitHub.