{"record":{"id":"ec25a56bdb695139","repo":"dotnet/wpf","slug":"sr-cantsetreadonlyproperty","errorCode":null,"errorMessage":"SR.CantSetReadonlyProperty","messagePattern":"SR\\.CantSetReadonlyProperty","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlMemberInvoker.cs","lineNumber":76,"sourceCode":"            }\n\n            if (UnderlyingGetter.IsStatic)\n            {\n                return UnderlyingGetter.Invoke(null, new object[] { instance });\n            }\n            else\n            {\n                return UnderlyingGetter.Invoke(instance, Array.Empty<object>());\n            }\n        }\n\n        public virtual void SetValue(object instance, object value)\n        {\n            ArgumentNullException.ThrowIfNull(instance);\n            ThrowIfUnknown();\n            if (UnderlyingSetter is null)\n            {\n                throw new NotSupportedException(SR.Format(SR.CantSetReadonlyProperty, _member));\n            }\n\n            if (UnderlyingSetter.IsStatic)\n            {\n                UnderlyingSetter.Invoke(null, new object[] { instance, value });\n            }\n            else\n            {\n                UnderlyingSetter.Invoke(instance, new object[] { value });\n            }\n        }\n\n        internal static XamlMemberInvoker DirectiveInvoker\n        {\n            get\n            {\n                if (s_Directive is null)\n                {","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlMemberInvoker.cs#L58-L94","documentation":"XamlMemberInvoker.SetValue writes the member's value via its underlying setter. When the member has no setter (read-only property), NotSupportedException with SR.CantSetReadonlyProperty (formatted with the member) is thrown since there is no setter to invoke.","triggerScenarios":"Calling invoker.SetValue(instance, value) where the XamlMember wraps a read-only property (getter only, UnderlyingSetter is null), e.g. `invoker.SetValue(obj, val)` on a collection-returning or computed property.","commonSituations":"XAML object-writer/property-injection code applying values generically; settings copies via reflection where read-only collections (e.g. Keys, Dimensions) are targeted; deserializers not honoring read-only members.","solutions":["Check `invoker.UnderlyingSetter is null` (or member.IsWritePublic / CanWrite) before calling SetValue.","For read-only collection properties, get the instance via GetValue and call Add on it rather than SetValue.","Add a setter to the target property if writing is truly required."],"exampleFix":"// before\nmember.Invoker.SetValue(obj, newList); // NotSupportedException on read-only property\n// after\nif (member.Invoker.UnderlyingSetter is not null)\n    member.Invoker.SetValue(obj, newList);\nelse if (member.Invoker.GetValue(obj) is IList list)\n{\n    list.Clear();\n    foreach (var item in (IEnumerable)newList) list.Add(item);\n}","handlingStrategy":"type-guard","validationCode":"bool canWrite = member.Invoker.UnderlyingSetter is not null;","typeGuard":"static bool CanWrite(XamlMember m) => m.Invoker.UnderlyingSetter is not null;","tryCatchPattern":"try { invoker.SetValue(instance, value); }\ncatch (NotSupportedException) { /* read-only member: use GetValue + mutation or skip */ }","preventionTips":["Check CanWrite/UnderlyingSetter before generic SetValue calls","Mutate read-only collections in place (GetValue then Add)","Design DTOs consumed by XAML writers with setters where population is expected"],"tags":["wpf","system-xaml","not-supported-exception","read-only-property"],"backgroundTag":"unsupported-operation","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"}