OrchardCMS/OrchardCore · error · FileStoreException

Cannot delete root directory.

Error message

Cannot delete root directory.

What it means

AwsFileStorage refuses to delete the store's root: TryDeleteDirectoryAsync requires a non-empty, non-whitespace path because deleting it would wipe every object under the base prefix. This is a defensive guard against accidental whole-store deletion.

Solutions

  1. Guard call sites: skip deletion when the computed path is null/empty/whitespace
  2. Trim leading slashes and re-check before invoking TryDeleteDirectoryAsync
  3. Ensure media folder deletion logic never targets the root container — special-case it to clear contents instead
  4. Fix path parsing so it cannot collapse a real folder path to empty

Example fix

// before
await fileStore.TryDeleteDirectoryAsync(folder.Path); // Path may be ""
// after
if (!string.IsNullOrWhiteSpace(folder.Path))
{
    await fileStore.TryDeleteDirectoryAsync(folder.Path.TrimStart('/'));
}
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(path) || path.Trim('/', ' ') is "")
    return; // refuse to delete root — never call TryDeleteDirectoryAsync with an empty path

Type guard

bool IsRootPath(string p) => string.IsNullOrWhiteSpace(p) || p.Trim('/', ' ').Length == 0;

Try / catch

try { await fileStore.TryDeleteDirectoryAsync(path); } catch (FileStoreException ex) when (ex.Message == "Cannot delete root directory.") { _logger.LogWarning("Refused root deletion attempt for {Path}", path); }

Prevention

When it happens

Trigger: Calling TryDeleteDirectoryAsync(null), TryDeleteDirectoryAsync("") or a whitespace-only path; calling TryDeleteDirectoryAsync("/") normalized to empty; content code that computes an empty directory path (e.g. deleting a container whose path resolved to root).

Common situations: Path-trimming bugs where splitting a full path yields an empty directory segment; recursively deleting parent folders until root is reached; admin bulk-delete operations on top-level media folders with empty path values.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/07b2abff508a3c70. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.FileStorage.AmazonS3/AwsFileStorage.cs:163

            });

            return response.IsDeleteSuccessful();
        }
        catch (AmazonS3Exception ex) when (ex.StatusCode == HttpStatusCode.NotFound)
        {
            return false;
        }
        catch (AmazonS3Exception ex)
        {
            throw new FileStoreException($"Error deleting file '{path}': {ex.Message}", ex);
        }
    }

    public async Task<bool> TryDeleteDirectoryAsync(string path)
    {
        if (string.IsNullOrWhiteSpace(path))
        {
            throw new FileStoreException("Cannot delete root directory.");
        }

        var listObjectsResponse = await _amazonS3Client.ListObjectsV2Async(new ListObjectsV2Request
        {
            BucketName = _options.BucketName,
            Prefix = NormalizePrefix(this.Combine(_basePrefix, path)),
        });

        if (listObjectsResponse.S3Objects?.Count > 0)
        {
            var deleteObjectsRequest = new DeleteObjectsRequest
            {
                BucketName = _options.BucketName,
                Objects = listObjectsResponse.S3Objects
                    .Select(metadata => new KeyVersion { Key = metadata.Key }).ToList(),
            };

            var response = await _amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest);

View on GitHub (pinned to 4306c0717f)