OrchardCMS/OrchardCore · error · FileStoreException

Cannot delete file ' '.

Error message

Cannot delete file '{path}'.

What it means

BlobFileStore.TryDeleteFileAsync calls DeleteIfExistsAsync on the blob client; any exception from the delete call is wrapped in a FileStoreException 'Cannot delete file {path}'. A missing blob is not an error (the method returns false), so this indicates a real failure reaching or authorizing the delete. It is also invoked from MoveFileAsync, where a failure during the move's delete step surfaces here.

Solutions

  1. Inspect the inner exception status: 403 → grant delete permission or check immutability/legal-hold policy; 409/412 → blob is leased, release the lease or retry later.
  2. Verify the configured identity has Storage Blob Data Contributor (or delete rights) on the container.
  3. Handle the false return as 'file was not there' — only treat the exception as a genuine failure.
  4. For MoveFileAsync failures, check whether the destination copy succeeded and clean up/redo the move idempotently.

Example fix

// before
await fileStore.TryDeleteFileAsync(oldPath); // may throw if lease held
// after
try
{
    await fileStore.TryDeleteFileAsync(oldPath);
}
catch (FileStoreException) when (await fileStore.GetFileInfoAsync(oldPath) == null)
{
    // already gone; ignore
}
Defensive patterns

Strategy: try-catch

Validate before calling

var file = await fileStore.GetFileInfoAsync(path);
if (file == null)
{
    return true; // nothing to delete — treat as success/no-op
}

Try / catch

try
{
    await fileStore.TryDeleteFileAsync(path);
}
catch (FileStoreException ex)
    when ((ex.InnerException as RequestFailedException)?.Status is 409 or 412 or 403)
{
    logger.LogWarning(ex, "Blob delete blocked (lease/hold/permissions) for {Path}", path);
    // schedule retry after lease release or fix policy/permissions
}

Prevention

When it happens

Trigger: Calling TryDeleteFileAsync(path) when DeleteIfExistsAsync throws — 403 authorization failure (no delete permission / immutable blob), 412 lease conflict (blob locked by a lease), 409 snapshot-in-progress, network/service errors, or from MoveFileAsync when deleting the source after copy fails.

Common situations: Blobs with active leases (another process holds a lease); immutability policies / legal hold on the container; identity lacking Storage Blob Data Contributor delete rights; transient Azure errors; concurrent MoveFileAsync operations contending on the same blob.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at src/OrchardCore/OrchardCore.FileStorage.AzureBlob/BlobFileStore.cs:473

            throw;
        }
        catch (Exception ex)
        {
            throw new FileStoreException($"Cannot create directory '{path}'.", ex);
        }
    }

    public async Task<bool> TryDeleteFileAsync(string path)
    {
        try
        {
            var blob = GetBlobReference(path);

            return await blob.DeleteIfExistsAsync();
        }
        catch (Exception ex)
        {
            throw new FileStoreException($"Cannot delete file '{path}'.", ex);
        }
    }

    public async Task<bool> TryDeleteDirectoryAsync(string path)
    {
        await EnsureCapabilitiesAsync();

        if (_capabilities?.HasHierarchicalNamespace == true)
        {
            try
            {
                if (string.IsNullOrEmpty(path))
                {
                    throw new FileStoreException("Cannot delete the root directory.");
                }

                var prefix = this.Combine(_basePrefix, path);
                var directoryClient = _dataLakeFileSystemClient.GetDirectoryClient(prefix);

View on GitHub (pinned to 4306c0717f)