AvaloniaUI/Avalonia · error · NotSupportedException

Property {Name} doesn't have a setter

Error message

Property {Name} doesn't have a setter

What it means

ClrPropertyInfo.Set() throws NotSupportedException when the property has no setter (_setter is null), i.e. it is read-only (get accessor only or computed). A TwoWay or OneWayToSource binding tries to push a value back and calls Set(), which fails.

Source

Thrown at src/Avalonia.Base/Data/Core/ClrPropertyInfo.cs:32

            _setter = setter;
            PropertyType = propertyType;
            Name = name;
        }

        public string Name { get; }
        public Type PropertyType { get; }

        public object? Get(object target)
        {
            if (_getter == null)
                throw new NotSupportedException("Property " + Name + " doesn't have a getter");
            return _getter(target);
        }

        public void Set(object target, object? value)
        {
            if (_setter == null)
                throw new NotSupportedException("Property " + Name + " doesn't have a setter");
            _setter(target, value);
        }

        public bool CanSet => _setter != null;
        public bool CanGet => _getter != null;
    }

    public class ReflectionClrPropertyInfo : ClrPropertyInfo
    {
        private static Action<object, object?>? CreateSetter(PropertyInfo info)
            => info.SetMethod is { } setMethod ?
                (target, value) => setMethod.Invoke(target, [value]) :
                null;

        private static Func<object, object?>? CreateGetter(PropertyInfo info)
            => info.GetMethod is { } getMethod ?
                target => getMethod.Invoke(target, []) :
                null;

View on GitHub (pinned to 11c5427268)

Solutions

  1. Change the binding Mode to OneWay or OneTime so no write-back occurs.
  2. Make the source property mutable by adding a setter (and raising change notifications).
  3. Bind to a different settable property on the source.

Example fix

// before
public int Total { get; } = Compute();
<TextBox Text="{Binding Total}" />  <!-- defaults to TwoWay on TextBox.Text -->
// after
<TextBox Text="{Binding Total, Mode=OneWay}" />
Defensive patterns

Strategy: type-guard

Validate before calling

// Check CanSet before writing via ClrPropertyInfo, and verify mode is one-way if read-only.
if (propertyInfo is ClrPropertyInfo clr && !clr.CanSet && mode != BindingMode.OneWay && mode != BindingMode.OneTime)
    throw new InvalidOperationException($"{clr.Name} is read-only; use OneWay/OneTime.");

Type guard

static bool IsWritable(ClrPropertyInfo p) => p.CanSet;

Try / catch

try { propertyInfo.Set(target, value); }
catch (NotSupportedException) { /* read-only: ignore or log */ }

Prevention

When it happens

Trigger: A TwoWay or OneWayToSource binding whose target path ends on a read-only CLR property, so the engine attempts Set() and there is no setter to invoke.

Common situations: Binding TextBox.Text TwoWay to a computed/readonly viewmodel property; binding to a get-only property while mode resolves to TwoWay (TextBox.Text default); targeting an immutable record property.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/8f7c36e58cedcde8. Report an issue: GitHub.