dotnet/wpf · error · IOException
SR.CanNotDelete
Error message
SR.CanNotDelete
What it means
StorageInfo.DeleteSubStorage catches a COMException from IStorage::DestroyElement whose error code is not STG_E_ACCESSDENIED and throws IOException with SR.CanNotDelete. It is the generic 'we could not delete this sub-storage' path for any COM failure other than access denied (e.g. element busy, name invalid, file corruption).
Solutions
- Inspect the inner COMException's HResult to identify the underlying STG_E_* code.
- Close all StreamInfo/StorageInfo objects and enumerators derived from the container before deleting.
- Verify the file is not corrupt by opening it in the owning application or repairing it.
- Retry on a writable copy of the file if the original medium is suspect.
Example fix
// before
storageInfo.DeleteSubStorage(name); // throws IOException
// after
try { storageInfo.DeleteSubStorage(name); }
catch (IOException e) when (e.InnerException is COMException ce) {
// inspect ce.HResult (STG_E_* code) and handle/retry
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!File.Exists(path)) throw new FileNotFoundException(path);
if (new FileInfo(path).Length == 0) throw new InvalidDataException("Empty compound file"); Prevention
- Close all child StreamInfo/StorageInfo/enumerators before deleting.
- Validate the file opens in the owning application (not corrupt).
- Work on a writable local copy rather than the original medium.
When it happens
Trigger: Calling DeleteSubStorage/Delete on a storage whose IStorage::DestroyElement fails with any HRESULT other than STG_E_ACCESSDENIED — corrupt compound file, storage opened in a sharing-incompatible mode, or a name that does not resolve.
Common situations: Deleting entries in a truncated or partially-written compound document; deleting a sub-storage while enumerators/streams are still bound to it in conflicting modes; media or file-system I/O errors.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- SR.CanNotOpenStorage
- Read
- SR.CanNotCreateContainerOnReadOnlyStream
- SR.CanNotCreateStorageRootOnNonReadableStream
- SR.CanNotOnNonExistStorage
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/c7ffda6ec3dc7a4f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/CompoundFile/StorageInfo.cs:792
}
}
// Make the call to the underlying OLE mechanism to remove the element.
try
{
core.safeIStorage.DestroyElement( elementNameInternal );
}
catch( COMException e )
{
if( e.ErrorCode == SafeNativeCompoundFileConstants.STG_E_ACCESSDENIED )
{
throw new UnauthorizedAccessException(
SR.CanNotDeleteAccessDenied,
e );
}
else
{
throw new IOException(
SR.CanNotDelete,
e );
}
}
// Invalidate enumerators
InvalidateEnumerators();
// Remove the now-meaningless name, which also signifies disposed status.
if (deadElementWalking is StorageInfoCore deadStorageInfoCore)
{
// Erase this storage's existence
deadStorageInfoCore.storageName = null;
if (null != deadStorageInfoCore.safeIStorage)
{
((IDisposable)deadStorageInfoCore.safeIStorage).Dispose();
deadStorageInfoCore.safeIStorage = null;View on GitHub (pinned to 81131a70a4)