dotnet/wpf · error · ObjectDisposedException
SR.StreamObjectDisposed
Error message
SR.StreamObjectDisposed
What it means
CFStream.CheckDisposedStatus throws ObjectDisposedException with SR.StreamObjectDisposed when any member (Length, Position, Flush, Seek, SetLength, Read, Write) is used after the CFStream has been disposed. Compound-file streams wrap native IStream handles that are released on Dispose, so further use is impossible. This is standard Stream disposed-state enforcement.
Solutions
- Keep all stream usage inside the using/scope where the stream is alive
- Check the parent CompoundFile/Package lifetime — disposing it disposes child streams
- Track disposal with stream.CanRead (false after dispose) or a null-check after ownership transfer
- Restructure so async work completes before disposing the owning file
- Catch ObjectDisposedException as a last-resort guard in event handlers
Example fix
// before
Stream s;
using (var cf = new CompoundFile(path)) {
s = cf.OpenStream(name);
}
s.Read(buf, 0, buf.Length); // throws
// after
using (var cf = new CompoundFile(path)) {
using (var s = cf.OpenStream(name)) {
s.Read(buf, 0, buf.Length);
}
} Defensive patterns
Strategy: type-guard
Validate before calling
if (stream == null || !stream.CanRead) throw new ObjectDisposedException(nameof(stream));
Type guard
static bool IsUsable(Stream s) => s != null && s.CanRead;
Try / catch
try { stream.Read(buffer, 0, count); } catch (ObjectDisposedException) { /* reopen the stream */ } Prevention
- Confine stream usage to using blocks; never let references escape
- Know the owner: disposing the CompoundFile/Package disposes its streams
- Complete async work before disposing the owning object
- Set fields to null after disposal to fail fast on stale references
When it happens
Trigger: Calling Read/Seek/Length/Position/Flush/SetLength/Write after calling Dispose() or after the containing CompoundFile was closed/disposed; using a stream captured in a lambda or event handler that fires after disposal.
Common situations: Using-block scope bugs where a stream reference escapes the using block; closing the parent Package/compound file while child streams are still referenced; async continuations running after the stream was disposed.
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
- SR.StreamObjectDisposed
- SR.StreamObjectDisposed
- ArgumentOutOfRangeException(nameof(offset))
- can’t seek on baseStream
- Current stream object was closed and disposed. Cannot…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/d2e76dfcdf31bedb.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/CFStream.cs:283
}
if( count != written )
throw new IOException(
SR.WriteFailure);
}
//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
// Check whether this Stream object is still valid. If not, thrown an
// ObjectDisposedException.
internal void CheckDisposedStatus()
{
if( StreamDisposed )
throw new ObjectDisposedException(null, SR.StreamObjectDisposed);
}
// Check whether this Stream object is still valid.
internal bool StreamDisposed
{
get
{
return (backReference.StreamInfoDisposed || ( null == _safeIStream ));
}
}
// Constructors
internal CFStream(
IStream underlyingStream,
FileAccess openAccess,
StreamInfo creator)
{
_safeIStream = underlyingStream;View on GitHub (pinned to 81131a70a4)