dotnet/wpf · error · ObjectDisposedException
Cannot access Stream object because it was closed or…
Error message
Cannot access Stream object because it was closed or disposed.
What it means
UnsafeLockBytesOnStream implements CheckDisposed, called by every ILockBytes operation (ReadAt, WriteAt, Flush, SetSize, Stat). After Dispose has been called, _baseStream is set to null, and any subsequent operation throws ObjectDisposedException with the 'Cannot access Stream object because it was closed or disposed' message.
Solutions
- Ensure the underlying stream lives as long as all uses of the compound file; only dispose once, after all operations complete.
- Guard accesses with a disposed check, or catch ObjectDisposedException where post-dispose calls are benign.
- Restructure so callbacks/async work complete before disposing the owning Package.
Example fix
// before package.Close(); var stat = lockBytes.Stat(0); // throws // after var stat = lockBytes.Stat(0); package.Close();
Defensive patterns
Strategy: try-catch
Validate before calling
bool usable = lockBytes != null && !isDisposed; // track your own disposed flag
Type guard
bool IsAlive(UnsafeLockBytesOnStream lb) => lb != null && !lb.Disposed;
Try / catch
try { lockBytes.Stat(grfStatFlag); }
catch (ObjectDisposedException) { /* stream was closed; reopen or abort */ } Prevention
- Dispose exactly once, after all operations complete
- Avoid double disposal (using-block + explicit Close)
- Ensure async/callback work finishes before closing the parent Package
When it happens
Trigger: Calling any ILockBytes/IStream operation after UnsafeLockBytesOnStream.Dispose() — e.g. using the compound file object after its owning Package/stream was closed, or a callback firing after disposal.
Common situations: Double-closing a Package (using-block plus explicit Dispose), holding a reference to a compound-file stream after the parent package is closed, or async operations outliving the stream's lifetime.
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.ByteRangeDownloaderDisposed
- SR.StorageRootDisposed
- SR.StreamObjectDisposed
- SR.StreamObjectDisposed
- SR.StreamObjectDisposed
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/e361beb0b4196a1e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/PrivateUnsafeNativeCompoundFileMethods.cs:105
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing && (_baseStream != null))
{
// We only set the _baseStream to null without closing it,
// because _baseStream is a reference of an outside stream,
// and was set when this class was constructed. We didn't open
// the stream and should leave the original owner of the stream
// to close it.
_baseStream = null;
}
}
private void CheckDisposed()
{
if (_baseStream==null)
{
throw new ObjectDisposedException(null, SR.StreamObjectDisposed);
}
}
void UnsafeNativeILockBytes.ReadAt (
UInt64 offset,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] Byte[] pv,
int cb,
out int pcbRead)
{
CheckDisposed();
checked { _baseStream.Seek( (long)offset, SeekOrigin.Begin ); }
pcbRead = _baseStream.Read( pv, 0, cb );
}
void UnsafeNativeILockBytes.WriteAt(
UInt64 offset,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] Byte[] pv,
int cb,View on GitHub (pinned to 81131a70a4)