dotnet/wpf · error · ObjectDisposedException
Current stream object was closed and disposed. Cannot…
Error message
Current stream object was closed and disposed. Cannot access a closed stream.
What it means
ByteStream wraps a Stream for WPF packaging and tracks disposal via a StreamDisposed flag. Any member (Length, Position, Seek, Read) calls CheckDisposedStatus() first and throws ObjectDisposedException once the underlying stream has been closed/disposed. It prevents use-after-dispose on package part streams.
Solutions
- Keep the source stream (and its Package) open until all reads of the package part are finished; scope using blocks around all consuming code.
- Wrap stream access in try-catch for ObjectDisposedException and re-open the stream if it was closed.
- Check the stream's CanRead property before accessing it and reopen/re-create the ByteStream when it is false.
Example fix
// before
using (var fs = File.OpenRead(path)) {
var bs = new ByteStream(fs);
QueueReadLater(bs); // fs disposed here -> later access throws
}
// after
var fs = File.OpenRead(path);
var bs = new ByteStream(fs);
try {
ReadAll(bs); // consume while stream is open
} finally {
fs.Dispose();
} Defensive patterns
Strategy: try-catch
Validate before calling
if (stream == null || !stream.CanRead) { /* re-open the stream before constructing/using ByteStream */ } Type guard
static bool IsUsable(Stream s) => s != null && (s.CanRead || s.CanWrite);
Try / catch
try { var len = byteStream.Length; } catch (ObjectDisposedException) { /* re-open stream and retry */ } Prevention
- Scope using/dispose blocks around ALL code that touches the package part stream
- Never store ByteStream/Stream references beyond the lifetime of their owner Package
- Check CanRead before delayed or deferred reads
When it happens
Trigger: Calling Read, Seek, Position, or Length on a ByteStream after its Stream was closed via Stream.Close()/Dispose(), or after the containing package was closed and disposed its part streams.
Common situations: Disposing a Package or FileStream in a using block while still reading XPS/package parts from it; closing the stream in a finally block before a delayed read; sharing a stream between code paths where one disposes it early.
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
- ArgumentOutOfRangeException(nameof(offset))
- ArgumentOutOfRangeException: offset is outside the valid…
- BaseStream
- can’t seek on baseStream
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9f9189bc89bee383.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/IO/Packaging/ByteStream.cs:346
#endregion Public Methods
//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
#region Internal Methods
/// <summary>
/// Check whether this Stream object is still valid. If not, thrown an
/// ObjectDisposedException.
/// </summary>
internal void CheckDisposedStatus()
{
if (StreamDisposed)
throw new ObjectDisposedException(null, SR.StreamObjectDisposed);
}
#endregion Internal Methods
//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
#region Internal Properties
/// <summary>
/// Check whether this Stream object is still valid.
/// </summary>
private bool StreamDisposed
{
getView on GitHub (pinned to 81131a70a4)