dotnet/wpf · error · InvalidOperationException
SR.CanNotDeleteRoot
Error message
SR.CanNotDeleteRoot
What it means
Thrown by StorageInfo.Delete when attempting to delete the root storage of a compound file. The root storage has no parent (parentStorage is null), so 'deleting' it is meaningless and would leave the file object in an invalid state; the library raises InvalidOperationException to indicate a caller logic error.
Solutions
- Only call Delete on non-root storages (check parentStorage != null)
- Delete individual child storages/streams instead of the root; to clear a file, delete children or overwrite the file
- Guard recursive cleanup with an isRoot check before invoking Delete
- Close and delete the whole file at the filesystem level if the intent is to remove the package entirely
Example fix
// before foreach (var s in storages) s.Delete(true); // storages includes root // after foreach (var s in storages.Where(s => s != root)) s.Delete(true);
Defensive patterns
Strategy: type-guard
Validate before calling
if (storage.parentStorage == null) throw new InvalidOperationException("Cannot delete the root storage"); Type guard
bool IsRoot(StorageInfo s) => s.parentStorage == null; // skip roots in delete loops
Try / catch
try { storage.Delete(recursive); }
catch (InvalidOperationException ex) { /* root deletion attempt: skip or rethrow */ } Prevention
- Never call Delete on StorageRoot
- Filter out the root in recursive tree cleanup
- To remove an entire package, delete the file itself instead
When it happens
Trigger: Calling Delete() or Delete(name) on the StorageRoot/root StorageInfo instance obtained from StorageRoot.OpenOnFile/OpenOnStream.
Common situations: Recursive cleanup code that walks a storage tree and deletes children but recurses into or mis-targets the root; generic 'delete everything' helpers that pass the root node.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- ' ' name is already in use.
- SR.CanNotDeleteNonEmptyStorage
- SR.StorageAlreadyExist
- SR.StorageNotExist
- SR.UnableToCreateStorage
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/c62dc88136690784.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/CompoundFile/StorageInfo.cs:693
}
// Return a reference
return newSubStorage;
}
/// <summary>
/// Deletes a storage, recursively if specified.
/// </summary>
/// <param name="recursive">Whether to recursive delete all existing content</param>
/// <param name="name">Name of storage</param>
internal bool Delete( bool recursive , string name)
{
bool storageDeleted = false;
CheckDisposedStatus();
if( null == parentStorage )
{
// We are the root storage, you can't "delete" the root storage!
throw new InvalidOperationException(
SR.CanNotDeleteRoot);
}
if( InternalExists(name) )
{
if( !recursive && !StorageIsEmpty())
{
throw new IOException(
SR.CanNotDeleteNonEmptyStorage);
}
InvalidateEnumerators();
// Go ahead and delete "this" storage
parentStorage.DestroyElement( name );
storageDeleted = true;
}
//We will not throw exceptions if the storage does not exist. This is to be consistent with Package.DeletePart.
View on GitHub (pinned to 81131a70a4)