{"record":{"id":"44821797a66b2479","repo":"dotnet/wpf","slug":"sr-streamobjectdisposed-versionedstream","errorCode":null,"errorMessage":"SR.StreamObjectDisposed","messagePattern":"SR\\.StreamObjectDisposed","errorType":"exception","errorClass":"ObjectDisposedException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/VersionedStream.cs","lineNumber":256,"sourceCode":"                {\n                    _stream.Close();\n                }\n            }\n            finally\n            {\n                _stream = null;\n                base.Dispose(disposing);\n            }\n        }\n\n        /// <summary>\n        /// Call this before accepting any public API call (except some Stream calls that\n        /// are allowed to respond even when Closed\n        /// </summary>\n        protected void CheckDisposed()\n        {\n            if (_stream == null)\n                throw new ObjectDisposedException(null, SR.StreamObjectDisposed);\n        }\n\n        //------------------------------------------------------\n        //\n        //  Private Fields\n        //\n        //------------------------------------------------------\n        private VersionedStreamOwner    _versionOwner;\n        private Stream                  _stream;            // null indicates Disposed state\n    }\n}\n","sourceCodeStart":238,"sourceCodeEnd":268,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/VersionedStream.cs#L238-L268","documentation":"ObjectDisposedException (message SR.StreamObjectDisposed) thrown by VersionedStream.CheckDisposed when a public Stream API (Length, Position, Flush, Seek, SetLength, Read) is used after the underlying stream was closed (its _stream field set to null). It is the standard 'use after close' guard for versioned compound-file streams.","triggerScenarios":"Calling any read/seek/flush member of a VersionedStream after Close()/Dispose() was called on it — e.g. keeping a reference to the stream after the CompoundFile/package was disposed, or finishing a using block and then reading Position.","commonSituations":"Disposing a package in a using block but retaining stream references in fields or closures; deferred/lazy reads (e.g. in async code or event handlers) that run after disposal; double-dispose followed by an accidental access.","solutions":["Read all needed data before the owning package/CompoundFile is disposed","Reopen the compound file/package to obtain a fresh stream instead of reusing the closed one","Restructure code so stream lifetime matches usage scope (keep the owning object alive while the stream is referenced)","Guard accesses with an IsDisposed/can-read check when the stream may already be closed"],"exampleFix":"// before: using a stream after the package was disposed\nPackage package;\nusing (package = Package.Open(path))\n{\n    partStream = part.GetStream();\n}\nlong len = partStream.Length; // ObjectDisposedException\n// after: consume the stream inside the owning package's lifetime\nusing (var package = Package.Open(path))\n{\n    using (var partStream = part.GetStream())\n    {\n        long len = partStream.Length; // OK\n        ProcessStream(partStream);\n    }\n}","handlingStrategy":"try-catch","validationCode":"static bool IsUsable(Stream s) => s != null && s.CanRead && s.CanSeek; // CanRead/CanSeek are false after disposal on most streams","typeGuard":"bool IsAliveStream(VersionedStream vs) => vs != null && vs.CanRead;","tryCatchPattern":"try\n{\n    long len = versionedStream.Length;\n}\ncatch (ObjectDisposedException)\n{\n    // reopen the owning package/stream and retry once\n    using (var fresh = ReopenStream())\n    {\n        len = fresh.Length;\n    }\n}","preventionTips":["Scope stream usage inside the owning package's using block","Never store package streams in long-lived fields or closures","Read all needed bytes eagerly if the package's lifetime is uncertain","Enable dispose-pattern analyzers to catch use-after-dispose"],"tags":["object-disposed","stream-lifetime","wpf","packaging"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}