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
- Keep the Package/root open for the lifetime of all StreamInfo operations
- Check StreamInfoDisposed (or wrap in try/catch ObjectDisposedException) before use
- Re-open the package and re-obtain the StreamInfo after disposal
- 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
- Scope all package/stream work inside the using block of the Package
- Never cache StreamInfo or PackagePart beyond package lifetime
- Re-open the package instead of reusing disposed objects
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
- Cannot access the stream after it is closed.
- SR.CryptoProviderDisposed
- SR.StorageInfoDisposed
- ' ' cannot contain the path delimiter: ' '.
- ' ' cannot start with the reserved character range…
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)