{"record":{"id":"906a437d9fd9fdae","repo":"dotnet/wpf","slug":"sr-streamobjectdisposed-compressemulationstream","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/CompressEmulationStream.cs","lineNumber":321,"sourceCode":"\n                        _disposed = true;\n                    }\n                }\n            }\n            finally\n            {\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 (_disposed)\n                throw new ObjectDisposedException(null, SR.StreamObjectDisposed);\n        }\n\n        #region Private\n        //------------------------------------------------------\n        //\n        //  Private Variables\n        //\n        //------------------------------------------------------\n        private bool    _disposed;          // disposed?\n        private bool    _dirty;             // do we need to recompress?\n        protected Stream  _baseStream;      // stream we ultimately decompress from and to in the container\n        protected Stream _tempStream;       // temporary storage for the uncompressed stream\n        private IDeflateTransform _transformer;   // does the actual compress/decompress for us\n        #endregion\n    }\n}\n","sourceCodeStart":303,"sourceCodeEnd":338,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompressEmulationStream.cs#L303-L338","documentation":"CompressEmulationStream.CheckDisposed guards every public API (Read, Write, Seek, SetLength, Flush, Position). Once Dispose has run, any further call throws ObjectDisposedException with SR.StreamObjectDisposed, mirroring System.IO.Stream conventions.","triggerScenarios":"Calling Read/Write/Seek/Position/SetLength/Flush on a CompressEmulationStream after Dispose or a closing 'using' block has completed — e.g. caching the stream beyond its scope or using it after the owning Package is closed.","commonSituations":"Storing the stream in a field and using it after the using-block exits; closing the parent package then reading; background tasks holding the stream past disposal; double-dispose followed by use.","solutions":["Keep the stream alive within the scope that uses it (move the using block outward).","Check or track disposal state before use, or re-open the stream when needed.","Do not use the stream after the owning Package/Part is closed; reopen the part instead.","Catch ObjectDisposedException at the boundary if lifetime is inherently racy."],"exampleFix":"// before\nStream s;\nusing (var es = new CompressEmulationStream(baseStream, temp, t))\n{\n    s = es;\n}\ns.Read(buf, 0, buf.Length); // throws\n// after\nusing (var es = new CompressEmulationStream(baseStream, temp, t))\n{\n    es.Read(buf, 0, buf.Length);\n}","handlingStrategy":"try-catch","validationCode":"bool SafeCanUse(CompressEmulationStream s) { try { _ = s.Position; return true; } catch (ObjectDisposedException) { return false; } }","typeGuard":"sealed class GuardedStream\n{\n    private CompressEmulationStream _s;\n    public bool TryUse(Action<CompressEmulationStream> action)\n    {\n        if (_s == null) return false;\n        try { action(_s); return true; }\n        catch (ObjectDisposedException) { return false; }\n    }\n}","tryCatchPattern":"try { es.Read(buf, 0, buf.Length); }\ncatch (ObjectDisposedException) { ReopenAndRetry(); }","preventionTips":["Keep the stream lifetime at least as long as all usages (scope the using block outward)","Never cache the stream beyond its owning Package's lifetime","Reopen the part instead of using it after close","Ensure background work completes before disposal"],"tags":["wpf","stream","object-disposed","lifetime","io"],"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"}