dotnet/wpf · error · ObjectDisposedException

SR.StreamObjectDisposed

Error message

SR.StreamObjectDisposed

What it means

ObjectDisposedException with message SR.StreamObjectDisposed thrown by SparseMemoryStream.CheckDisposed, called at the start of Length, Position, SetLength, Seek, Read and Write. SparseMemoryStream is the backing store for sparse in-memory package parts; once disposed its state (including block list) is invalid and any operation must fail.

Solutions

  1. Complete all reads/writes before disposing the package or part stream.
  2. Re-acquire the stream via part.GetStream() if it was closed.
  3. Guard long-lived references: null them out on dispose so misuse surfaces immediately.
  4. Restructure ownership so the stream's lifetime is contained in one scope.

Example fix

// before
_sparseStream = new SparseMemoryStream();
...
_sparseStream.Dispose();
_sparseStream.WriteByte(b); // throws
// after
_sparseStream.Dispose();
_sparseStream = null;
if (_sparseStream != null) _sparseStream.WriteByte(b);
Defensive patterns

Strategy: try-catch

Type guard

bool IsAlive(SparseMemoryStream s) => s is { CanRead: true } or { CanWrite: true };

Try / catch

try { stream.WriteByte(b); }
catch (ObjectDisposedException) { /* stream closed: reopen via owning package */ }

Prevention

When it happens

Trigger: Any stream operation on a SparseMemoryStream after Dispose — typically after the containing package or part stream was closed and the wrapped reference is reused.

Common situations: Retaining a MemoryStream-backed part stream across Package.Close; deferred writes to a part whose stream was disposed by an outer using; double-dispose followed by read.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/SparseMemoryStream.cs:454

        internal long MemoryConsumption
        {
            get
            {
                CheckDisposed();
                return _trackingMemoryStreamFactory.CurrentMemoryConsumption;
            }
        }

        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
        private void CheckDisposed()
        {
            if (_disposedFlag)
            {
                throw new ObjectDisposedException(SR.StreamObjectDisposed);
            }
        }

        private MemoryStreamBlock GetSearchBlockForOffset(long offset)
        {
            if (_searchBlock == null)
                _searchBlock = new MemoryStreamBlock(null, offset);
            else
                _searchBlock.Offset = offset;
            return _searchBlock;
        }

        private bool CanCollapseWithPreviousBlock(MemoryStreamBlock memStreamBlock,
                                                        long offset,
                                                        long length)
        {
            // There was an explicit request by the client not to merge near- by blocks
            if (!_autoCloseSmallBlockGaps || memStreamBlock == null)

View on GitHub (pinned to 81131a70a4)