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

  1. Keep the StorageRoot open as long as any StorageInfo/StreamInfo objects are in use.
  2. Re-open the root and re-fetch storages after disposal instead of reusing old objects.
  3. Check the root's disposed state (e.g. root disposed flag / stream CanRead) before use.
  4. 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

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


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)