AvaloniaUI/Avalonia · error · InvalidOperationException

Cannot register a non-attached property as attached.

Error message

Cannot register a non-attached property as attached.

What it means

Thrown by AvaloniaPropertyRegistry.RegisterAttached when the property being registered has IsAttached == false. Attached and non-attached properties are stored in separate dictionaries; registering a normal styled/direct property through the attached path is a programming error.

Source

Thrown at src/Avalonia.Base/AvaloniaPropertyRegistry.cs:490

        /// <summary>
        /// Registers an attached <see cref="AvaloniaProperty"/> on a type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="property">The property.</param>
        /// <remarks>
        /// You won't usually want to call this method directly, instead use the
        /// <see cref="AvaloniaProperty.RegisterAttached{THost, TValue}(string, Type, TValue, bool, Data.BindingMode, Func{TValue, bool}, Func{AvaloniaObject, TValue, TValue})"/>
        /// method.
        /// </remarks>
        public void RegisterAttached(Type type, AvaloniaProperty property)
        {
            _ = type ?? throw new ArgumentNullException(nameof(type));
            _ = property ?? throw new ArgumentNullException(nameof(property));
            
            if (!property.IsAttached)
            {
                throw new InvalidOperationException(
                    "Cannot register a non-attached property as attached.");
            }
            lock (_unregisteringLocker)
            {
                if (!_attached.TryGetValue(type, out var inner))
                {
                    inner = new Dictionary<int, AvaloniaProperty>();
                    inner.Add(property.Id, property);
                    _attached.Add(type, inner);
                }
                else
                {
                    inner.Add(property.Id, property);
                }
            
                _attachedCache.Clear();
                _inheritedCache.Clear();
            }

View on GitHub (pinned to 11c5427268)

Solutions

  1. Register non-attached properties with Register(type, property) instead of RegisterAttached.
  2. If the property should be attached, create it with AvaloniaProperty.RegisterAttached so IsAttached is true.
  3. Guard with a check on property.IsAttached before choosing the registration API.

Example fix

// before
registry.RegisterAttached(ownerType, MyControl.FooProperty); // FooProperty is non-attached

// after
if (property.IsAttached) registry.RegisterAttached(ownerType, property);
else registry.Register(ownerType, property);
Defensive patterns

Strategy: validation

Validate before calling

if (property.IsAttached) registry.RegisterAttached(type, property); else registry.Register(type, property);

Type guard

static bool IsAttachedProperty(AvaloniaProperty p) => p.IsAttached;

Prevention

When it happens

Trigger: Calling RegisterAttached(type, property) with a property created via AvaloniaProperty.Register (not RegisterAttached); passing a regular StyledProperty or DirectProperty into the attached-registration API.

Common situations: Custom control code that wires registration manually and picks the wrong Register overload; copy-paste of a RegisterAttached call site applied to a non-attached property definition.

Related errors


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