dotnet/wpf · error · NotSupportedException

Cannot set read-only property

Error message

Cannot set read-only property '{0}'.

What it means

DynamicMethodRuntime.SetValue is called to assign a member's value, but the member's invoker has no UnderlyingSetter (the property is read-only). It throws NotSupportedException with CantSetReadonlyProperty ('Cannot set a read-only property {0}'). The library throws this because there is no setter method to invoke.

Solutions

  1. Remove the attribute/element that assigns the read-only property from the XAML
  2. Add a setter to the property if it should be settable from XAML
  3. For get-only collection properties, ensure the collection itself supports Add so the item elements can be appended instead of assigning the property

Example fix

// before
<Label ActualWidth="200" />  <!-- ActualWidth is read-only -->
// after
<Label Width="200" />
Defensive patterns

Strategy: try-catch

Validate before calling

static void EnsureSettable(Type t, string prop) { var p = t.GetProperty(prop); if (p != null && p.SetMethod == null) throw new InvalidOperationException($"{t}.{prop} is read-only and cannot be set from XAML"); }

Type guard

static bool IsXamlSettable(System.Reflection.PropertyInfo p) => p?.SetMethod is { IsPublic: true };

Try / catch

try { Load(xaml); } catch (NotSupportedException ex) when (ex.Message.Contains("read-only property")) { throw new InvalidOperationException($"Remove assignment to read-only member: {ex.Message}", ex); }

Prevention

When it happens

Trigger: XAML load attempts to set a member whose CLR property has no setter (get-only, or get-only collection property whose collection cannot accept items via add), or markup assigns a value to a read-only property like FrameworkElement.ActualWidth.

Common situations: Setting built-in read-only WPF properties (ActualWidth, Templatized values) in XAML; view-model properties exposed read-only but referenced by bindings/styles in parsed XAML; collection properties declared without a setter and with non-addable collections.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/07157dae41d848fa. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Runtime/DynamicMethodRuntime.cs:261

                throw new NotSupportedException(SR.Format(SR.CantGetWriteonlyProperty, member));
            }

            PropertyGetDelegate getterDelegate;
            if (!PropertyGetDelegates.TryGetValue(getter, out getterDelegate))
            {
                getterDelegate = CreateGetDelegate(getter);
                PropertyGetDelegates.Add(getter, getterDelegate);
            }

            return getterDelegate.Invoke(obj);
        }

        protected override void SetValue(XamlMember member, object obj, object value)
        {
            MethodInfo setter = member.Invoker.UnderlyingSetter;
            if (setter is null)
            {
                throw new NotSupportedException(SR.Format(SR.CantSetReadonlyProperty, member));
            }

            PropertySetDelegate setterDelegate;
            if (!PropertySetDelegates.TryGetValue(setter, out setterDelegate))
            {
                setterDelegate = CreateSetDelegate(setter);
                PropertySetDelegates.Add(setter, setterDelegate);
            }

            setterDelegate.Invoke(obj, value);
        }

        private DelegateCreator CreateDelegateCreator(Type targetType)
        {
            const BindingFlags helperFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly;

            // We are relying on WPF-generated delegate helper for now
            // Expected signature: internal Delegate _CreateDelegate(Type delegateType, string handler)

View on GitHub (pinned to 81131a70a4)