{"record":{"id":"f6491f6b6372b5ac","repo":"dotnet/wpf","slug":"sr-streamobjectdisposed-sparsememorystream","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/SparseMemoryStream.cs","lineNumber":454,"sourceCode":"        internal long MemoryConsumption\n        {\n            get\n            {\n                CheckDisposed();\n                return _trackingMemoryStreamFactory.CurrentMemoryConsumption;\n            }\n        }\n\n        //------------------------------------------------------\n        //\n        //  Private Methods\n        //\n        //------------------------------------------------------\n        private void CheckDisposed()\n        {\n            if (_disposedFlag)\n            {\n                throw new ObjectDisposedException(SR.StreamObjectDisposed);\n            }\n        }\n\n        private MemoryStreamBlock GetSearchBlockForOffset(long offset)\n        {\n            if (_searchBlock == null)\n                _searchBlock = new MemoryStreamBlock(null, offset);\n            else\n                _searchBlock.Offset = offset;\n            return _searchBlock;\n        }\n\n        private bool CanCollapseWithPreviousBlock(MemoryStreamBlock memStreamBlock,\n                                                        long offset,\n                                                        long length)\n        {\n            // There was an explicit request by the client not to merge near- by blocks\n            if (!_autoCloseSmallBlockGaps || memStreamBlock == null)","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/SparseMemoryStream.cs#L436-L472","documentation":"ObjectDisposedException with message SR.StreamObjectDisposed thrown by SparseMemoryStream.CheckDisposed, called at the start of Length, Position, SetLength, Seek, Read and Write. SparseMemoryStream is the backing store for sparse in-memory package parts; once disposed its state (including block list) is invalid and any operation must fail.","triggerScenarios":"Any stream operation on a SparseMemoryStream after Dispose — typically after the containing package or part stream was closed and the wrapped reference is reused.","commonSituations":"Retaining a MemoryStream-backed part stream across Package.Close; deferred writes to a part whose stream was disposed by an outer using; double-dispose followed by read.","solutions":["Complete all reads/writes before disposing the package or part stream.","Re-acquire the stream via part.GetStream() if it was closed.","Guard long-lived references: null them out on dispose so misuse surfaces immediately.","Restructure ownership so the stream's lifetime is contained in one scope."],"exampleFix":"// before\n_sparseStream = new SparseMemoryStream();\n...\n_sparseStream.Dispose();\n_sparseStream.WriteByte(b); // throws\n// after\n_sparseStream.Dispose();\n_sparseStream = null;\nif (_sparseStream != null) _sparseStream.WriteByte(b);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"bool IsAlive(SparseMemoryStream s) => s is { CanRead: true } or { CanWrite: true };","tryCatchPattern":"try { stream.WriteByte(b); }\ncatch (ObjectDisposedException) { /* stream closed: reopen via owning package */ }","preventionTips":["Tie stream usage to the package lifetime with using","Null out stream references after dispose","Avoid background tasks holding part-stream references"],"tags":["stream","objectdisposedexception","packaging","lifecycle"],"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"}