dotnet/wpf · error · ObjectDisposedException

StreamInfo object was disposed.

Error message

StreamInfo object was disposed.

What it means

CheckDisposedStatus throws ObjectDisposedException when the StreamInfo object has been disposed (name nulled in the core). After disposal the object no longer maps to a valid stream in the storage, so further use is invalid.

Solutions

  1. Keep the Package/root open for the lifetime of all StreamInfo operations
  2. Check StreamInfoDisposed (or wrap in try/catch ObjectDisposedException) before use
  3. Re-open the package and re-obtain the StreamInfo after disposal
  4. Restructure code so writes complete inside the using scope

Example fix

// before
using (var pkg = Package.Open(path)) { part = pkg.GetPart(uri); }
part.GetStream(); // ObjectDisposedException
// after
using (var pkg = Package.Open(path))
{
    var part = pkg.GetPart(uri);
    var s = part.GetStream(); // use inside scope
}
Defensive patterns

Strategy: validation

Validate before calling

bool usable = streamInfo != null && !streamInfo.StreamInfoDisposed; // internal; otherwise catch ObjectDisposedException
if (!usable) throw new InvalidOperationException("StreamInfo is disposed; re-open the package.");

Type guard

static bool IsUsable(StreamInfo si) => si != null; // disposed state is internal; pair with try/catch

Try / catch

try { var s = streamInfo.GetStream(name, FileMode.Open, FileAccess.Read); }
catch (ObjectDisposedException) { package = Package.Open(path); streamInfo = package.GetPart(uri).GetStreamInfo(); }

Prevention

When it happens

Trigger: Calling GetStream, Create, or Delete on a StreamInfo after its parent root/storage was closed or the StreamInfo was disposed (e.g. after Package.Close or StorageRoot.Dispose).

Common situations: Holding StreamInfo/PackageStream references beyond a using block around the Package; disposing the package then continuing to write parts in deferred cleanup code.

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/0dc4a9a43e037f4f. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/CompoundFile/StreamInfo.cs:740

            IStream cloneStream = null;
            core.safeIStream.Clone( out cloneStream );
            cloneStream.Seek( 0, SafeNativeCompoundFileConstants.STREAM_SEEK_SET, out dummy );

            Stream returnStream = 
                BuildStreamOnUnderlyingIStream( cloneStream, access, this );

            core.exposedStream = returnStream;

            return returnStream;
        }

        // Check whether this StreamInfo object is still valid.  If not, thrown an
        //  ObjectDisposedException.
        internal void CheckDisposedStatus()
        {
            // Check to see if we're still valid.
            if( StreamInfoDisposed ) // Null name in core signifies the core object is disposed
                throw new ObjectDisposedException(null, SR.StreamInfoDisposed);
        }

        // Check whether this StreamInfo object is still valid.  Return result.
        internal bool StreamInfoDisposed
        {
            get
            {
                // Check to see if we're still valid.
                // Null name in core signifies the core object is disposed.
                // Also check the parent storage.
                return (( null == core.streamName ) || parentStorage.StorageDisposed);
            }
        }


        // If we opened the IStream but haven't publicly exposed any Streams yet (i.e. InternalExists),
        // check to make sure the access modes match.
        internal void CheckAccessMode(int grfMode)

View on GitHub (pinned to 81131a70a4)