{"record":{"id":"ba91ec0f5bb9d4f4","repo":"dotnet/wpf","slug":"sr-writerisclosed","errorCode":null,"errorMessage":"SR.WriterIsClosed","messagePattern":"SR\\.WriterIsClosed","errorType":"exception","errorClass":"XamlException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/WriterDelegate.cs","lineNumber":76,"sourceCode":"        {\n            ThrowIsDisposed();\n            _addDelegate(XamlNodeType.Value, value);\n        }\n\n        public override void WriteNamespace(NamespaceDeclaration namespaceDeclaration)\n        {\n            ThrowIsDisposed();\n            _addDelegate(XamlNodeType.NamespaceDeclaration, namespaceDeclaration);\n        }\n\n        protected override void Dispose(bool disposing)\n        {\n            try\n            {\n                if (disposing && !IsDisposed)\n                {\n                    _addDelegate(XamlNodeType.None, XamlNode.InternalNodeType.EndOfStream);\n                    _addDelegate = delegate { throw new XamlException(SR.WriterIsClosed); };\n                    if (_addLineInfoDelegate is not null)\n                    {\n                        _addLineInfoDelegate = delegate { throw new XamlException(SR.WriterIsClosed); };\n                    }\n                }\n            }\n            finally\n            {\n                base.Dispose(disposing);\n            }\n        }\n\n        public override XamlSchemaContext SchemaContext\n        {\n            get { return _schemaContext; }\n        }\n        #endregion\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/WriterDelegate.cs#L58-L94","documentation":"WriterDelegate.Dispose installs a replacement _addDelegate that throws XamlException(SR.WriterIsClosed), so any node submitted to the writer after disposal fails. The delegate forwarding wrapper signals EndOfStream to the sink on dispose and then permanently closes its input.","triggerScenarios":"Calling any Write* method on the XamlWriter wrapper after Dispose() has run, which routes through the replaced throwing delegate.","commonSituations":"Using a writer after a using block or after the reader that owns it was disposed; buffered/writer chains where both owner and consumer call Dispose and later code still writes; exception-path cleanup followed by attempted final writes.","solutions":["Stop writing nodes once the writer is disposed; move any remaining writes before Dispose.","Check the writer's IsDisposed state before each write in defensive code paths.","Ensure only one component owns the writer lifecycle so Dispose is not called while writes are still pending.","Catch XamlException for WriterIsClosed if post-dispose writes must be tolerated."],"exampleFix":"// before\nusing (var w = new WriterDelegate(...)) { w.WriteEndMember(); }\nw.WriteEndMember(); // throws\n// after\nusing (var w = new WriterDelegate(...)) { w.WriteEndMember(); } // all writes inside the using","handlingStrategy":"try-catch","validationCode":"if (writer.IsDisposed) throw new InvalidOperationException(\"Cannot write to a disposed WriterDelegate.\");","typeGuard":"bool CanWrite(WriterDelegate w) => !w.IsDisposed;","tryCatchPattern":"try { writer.WriteStartMember(p); } catch (XamlException ex) when (/* WriterIsClosed */) { /* stop the pipeline; writer already disposed */ }","preventionTips":["Write all nodes before Dispose","Give one component ownership of writer disposal","Check IsDisposed before late writes"],"tags":["xaml","writer","disposed","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-21T21:30:21.729Z"}