dotnet/wpf · error · ObjectDisposedException
SR.StorageInfoDisposed
Error message
SR.StorageInfoDisposed
What it means
StorageInfo.CheckDisposedStatus throws ObjectDisposedException(null, SR.StorageInfoDisposed) when the underlying StorageRoot has been disposed (StorageDisposed is true). Using any StorageInfo/StreamInfo member after the root container is closed hits this guard.
Solutions
- Keep the StorageRoot open as long as any StorageInfo/StreamInfo objects are in use.
- Re-open the root and re-fetch storages after disposal instead of reusing old objects.
- Check the root's disposed state (e.g. root disposed flag / stream CanRead) before use.
- Restructure code so all compound-file work happens inside the root's using scope.
Example fix
// before
StorageInfo cached;
using (var root = StorageRoot.OpenOnStream(stream, FileMode.Open, FileAccess.Read, null))
cached = root.GetStorageInfo("Data");
cached.Exists; // ObjectDisposedException
// after
using (var root = StorageRoot.OpenOnStream(stream, FileMode.Open, FileAccess.Read, null))
{
var cached = root.GetStorageInfo("Data");
var exists = cached.Exists; // use inside scope
} Defensive patterns
Strategy: try-catch
Validate before calling
bool usable = rootStream != null && rootStream.CanRead && !rootDisposed;
if (!usable) throw new InvalidOperationException("Container root is closed"); Prevention
- Scope all StorageInfo/StreamInfo usage inside the root's using block.
- Do not cache child storages past root disposal.
- Track root lifetime explicitly (owner object holds and disposes it last).
When it happens
Trigger: Disposing or closing the StorageRoot (or the underlying stream/file) and then calling StorageInfo methods such as Exists, enumerators, Open, CreateSubStorage, or Delete on previously obtained child objects.
Common situations: Disposing the package/root in a using block but keeping cached StorageInfo/StreamInfo objects for later use; closing the file in a finally while background tasks still read storages.
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
- BaseStream
- SR.CanNotCreateContainerOnReadOnlyStream
- SR.CanNotCreateStorageRootOnNonReadableStream
- SR.CanNotDelete
- SR.CanNotOnNonExistStorage
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/309ce70b8a647758.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/CompoundFile/StorageInfo.cs:1258
// Free unmanaged resources associated with the startCore storage
if( null != startCore.safeIStorage)
{
((IDisposable) startCore.safeIStorage).Dispose();
startCore.safeIStorage = null;
}
// Null name in core signifies the core object is disposed
startCore.storageName = null;
}
}
// Check whether this StorageInfo is still valid. Throw if disposed.
internal void CheckDisposedStatus()
{
// null == parentStorage means we're root.
if( StorageDisposed )
throw new ObjectDisposedException(null, SR.StorageInfoDisposed);
}
// Check whether this StorageInfo is still valid.
internal bool StorageDisposed
{
get
{
// null == parentStorage means we're root.
if( null != parentStorage )
{
// Check our core reference to see if we're valid
if( null == core.storageName ) // Null name in core signifies the core object is disposed
{
// We have been deleted
return true;
}
// We're not the root storage - check parent.View on GitHub (pinned to 81131a70a4)