{"record":{"id":"63fb742b89f29c12","repo":"OrchardCMS/OrchardCore","slug":"cannot-delete-file-path","errorCode":null,"errorMessage":"Cannot delete file '{path}'.","messagePattern":"Cannot delete file '(.+?)'\\.","errorType":"exception","errorClass":"FileStoreException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.FileStorage.AzureBlob/BlobFileStore.cs","lineNumber":473,"sourceCode":"            throw;\n        }\n        catch (Exception ex)\n        {\n            throw new FileStoreException($\"Cannot create directory '{path}'.\", ex);\n        }\n    }\n\n    public async Task<bool> TryDeleteFileAsync(string path)\n    {\n        try\n        {\n            var blob = GetBlobReference(path);\n\n            return await blob.DeleteIfExistsAsync();\n        }\n        catch (Exception ex)\n        {\n            throw new FileStoreException($\"Cannot delete file '{path}'.\", ex);\n        }\n    }\n\n    public async Task<bool> TryDeleteDirectoryAsync(string path)\n    {\n        await EnsureCapabilitiesAsync();\n\n        if (_capabilities?.HasHierarchicalNamespace == true)\n        {\n            try\n            {\n                if (string.IsNullOrEmpty(path))\n                {\n                    throw new FileStoreException(\"Cannot delete the root directory.\");\n                }\n\n                var prefix = this.Combine(_basePrefix, path);\n                var directoryClient = _dataLakeFileSystemClient.GetDirectoryClient(prefix);","sourceCodeStart":455,"sourceCodeEnd":491,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.FileStorage.AzureBlob/BlobFileStore.cs#L455-L491","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Verify the configured identity has Storage Blob Data Contributor (or delete rights) on the container.","Handle the false return as 'file was not there' — only treat the exception as a genuine failure.","For MoveFileAsync failures, check whether the destination copy succeeded and clean up/redo the move idempotently."],"exampleFix":"// before\nawait fileStore.TryDeleteFileAsync(oldPath); // may throw if lease held\n// after\ntry\n{\n    await fileStore.TryDeleteFileAsync(oldPath);\n}\ncatch (FileStoreException) when (await fileStore.GetFileInfoAsync(oldPath) == null)\n{\n    // already gone; ignore\n}","handlingStrategy":"try-catch","validationCode":"var file = await fileStore.GetFileInfoAsync(path);\nif (file == null)\n{\n    return true; // nothing to delete — treat as success/no-op\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    await fileStore.TryDeleteFileAsync(path);\n}\ncatch (FileStoreException ex)\n    when ((ex.InnerException as RequestFailedException)?.Status is 409 or 412 or 403)\n{\n    logger.LogWarning(ex, \"Blob delete blocked (lease/hold/permissions) for {Path}\", path);\n    // schedule retry after lease release or fix policy/permissions\n}","preventionTips":["Handle false (missing blob) and thrown exceptions as distinct outcomes.","Check for immutability policies/legal holds and active leases before deleting.","Grant the identity Storage Blob Data Contributor for delete scenarios.","In MoveFileAsync flows, make moves idempotent so a failed delete of the source can be retried."],"tags":["azure","blob-storage","file-storage","delete","permission-denied"],"backgroundTag":"file-not-found","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}