AvaloniaUI/Avalonia · error · ArgumentException

The property {Name} is readonly.

Error message

The property {Name} is readonly.

What it means

DirectProperty maps an AvaloniaProperty to a direct CLR getter/setter pair on the owner. When Setter is null the property is read-only, so InvokeSetter (used by the binding/value system to write) throws ArgumentException. This prevents bindings or SetValue calls from writing to a getter-only direct property.

Source

Thrown at src/Avalonia.Base/DirectProperty.cs:118

                setter,
                metadata);

            AvaloniaPropertyRegistry.Instance.Register(typeof(TNewOwner), result);
            return result;
        }

        /// <inheritdoc/>
        internal override TValue InvokeGetter(AvaloniaObject instance)
        {
            return Getter((TOwner)instance);
        }

        /// <inheritdoc/>
        internal override void InvokeSetter(AvaloniaObject instance, BindingValue<TValue> value)
        {
            if (Setter == null)
            {
                throw new ArgumentException($"The property {Name} is readonly.");
            }

            if (value.HasValue)
            {
                Setter((TOwner)instance, value.Value);
            }
        }

        /// <inheritdoc/>
        object? IDirectPropertyAccessor.GetValue(AvaloniaObject instance)
        {
            return Getter((TOwner)instance);
        }

        /// <inheritdoc/>
        void IDirectPropertyAccessor.SetValue(AvaloniaObject instance, object? value)
        {
            if (Setter == null)

View on GitHub (pinned to 11c5427268)

Solutions

  1. Do not write to read-only direct properties; switch the binding to OneWay.
  2. If the property should be writable, register it with a setter lambda in AvaloniaProperty.RegisterDirect.
  3. Guard UI inputs that would push values back through a read-only property.

Example fix

// before:
public static readonly DirectProperty<Foo, int> BarProperty =
    AvaloniaProperty.RegisterDirect<Foo, int>(o => o.Bar);
// Bar has no setter; later:
foo.SetValue(BarProperty, 5); // throws

// after (make writable):
AvaloniaProperty.RegisterDirect<Foo, int>(o => o.Bar, (o, v) => o.Bar = v);
Defensive patterns

Strategy: validation

Validate before calling

var dp = (DirectProperty<TOwner, TValue>)property;
if (dp.Setter is null)
    throw new ArgumentException($"{dp.Name} is read-only.");

Type guard

static bool IsWritable(DirectProperty<TOwner, TValue> p) => p.Setter is not null;

Prevention

When it happens

Trigger: Calling SetValue on a read-only DirectProperty (one registered with `DirectPropertyBuilder<TOwner,TValue>.WithoutSetter()` or no setter supplied). A TwoWay/OneWayToSource binding targeting such a property. InvokeSetter invoked internally by the value store.

Common situations: Binding TwoWay to a read-only direct property. Calling control.SetValue(ReadOnlyProp, x). Registering a property without a setter then allowing user input to flow back.

Related errors


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