dotnet/wpf · error · ObjectDisposedException

SR.StorageRootDisposed

Error message

SR.StorageRootDisposed

What it means

This is an ObjectDisposedException thrown by StorageRoot.CheckRootDisposedStatus when the compound file's root storage has already been disposed (RootDisposed is true). The CompoundFile-based Packaging APIs (StorageRoot, StorageInfo, StreamInfo) invalidate the underlying OLE structured storage when the root is closed/disposed, and every non-static external API re-checks disposal before acting. It signals the developer called a packaging API after the owning CompoundFile/StorageRoot was closed.

Solutions

  1. Ensure all reads/writes complete before disposing the CompoundFile/Package; keep the owning object alive for the duration of use.
  2. Re-open the compound file (e.g. StorageRoot.Open / Package.Open) if you need access after disposal instead of reusing the old instance.
  3. Check RootDisposed (or guard with try/catch ObjectDisposedException) before calling APIs on long-lived references.
  4. Fix lifetime ownership: don't dispose in one layer while another layer still holds references.

Example fix

// before
var root = StorageRoot.Open(path); // disposed elsewhere/earlier
root.Flush(); // throws ObjectDisposedException
// after
using (var root = StorageRoot.Open(path))
{
    // do all work here, before disposal
    root.Flush();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (root == null || root.RootDisposed) throw new InvalidOperationException("Compound file root already disposed.");

Type guard

bool IsUsable(StorageRoot root) => root != null && !root.RootDisposed;

Try / catch

try { root.Flush(); }
catch (ObjectDisposedException) { /* reopen the compound file and retry the operation */ }

Prevention

When it happens

Trigger: Calling OpenAccess, Flush, or GetDataSpaceManager on a StorageRoot (or any StorageInfo/StreamInfo operation that routes through these) after the root compound file has been disposed/closed, e.g. using a Package or StreamInfo obtained before a 'using' block ended.

Common situations: Using a Package/StorageRoot inside a 'using' or after Close()/Dispose(); caching a StreamInfo/StreamInfo-derived object in a field and using it after the file was closed; closing the package in one method and writing in another.

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/2e4c13845cedc8f5. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/CompoundFile/StorageRoot.cs:443

            dataSpaceManager = new DataSpaceManager( this );
            dataSpaceManagerInitializationInProgress = false;
        }

        return dataSpaceManager;
    }

    internal IStorage GetRootIStorage()
    {
        return rootIStorage;
    }

    // Check whether this StorageRoot class still has its underlying storage.
    //  If not, throw an object disposed exception.  This should be checked from
    //  every non-static container external API.
    internal void CheckRootDisposedStatus()
    {
        if( RootDisposed )
            throw new ObjectDisposedException(null, SR.StorageRootDisposed);
    }

    // Check whether this StorageRoot class still has its underlying storage.
    internal bool RootDisposed
    {
        get
        {
            return ( null == rootIStorage );
        }
    }

    /// <summary>
    /// This will create a container StorageRoot based on the given IStorage
    /// interface
    /// </summary>
    /// <param name="root">The new IStorage (RCW) upon which to build the new StorageRoot</param>
    /// <returns>New StorageRoot object built on the given IStorage</returns>
    private static StorageRoot CreateOnIStorage( IStorage root )

View on GitHub (pinned to 81131a70a4)