AvaloniaUI/Avalonia · error · NotSupportedException

LogicalAncestorNode is invalid in conjunction with a binding

Error message

LogicalAncestorNode is invalid in conjunction with a binding source.

What it means

LogicalAncestorElementNode.SelectSource throws NotSupportedException when an explicit binding source is set (source != UnsetValue) together with a $parent logical-ancestor relative source. The logical-ancestor traversal walks the logical tree from the target, so an explicit Source is contradictory and not allowed.

Source

Thrown at src/Avalonia.Base/Data/Core/ExpressionNodes/LogicalAncestorElementNode.cs:45

            if (_ancestorType is not null)
            {
                builder.Append(_ancestorType.Name);
                if (_ancestorLevel > 0)
                    builder.Append(',');
            }

            if (_ancestorLevel > 0)
                builder.Append(_ancestorLevel);

            builder.Append(']');
        }
    }

    public override object? SelectSource(object? source, object target, object? anchor)
    {
        if (source != AvaloniaProperty.UnsetValue)
            throw new NotSupportedException(
                "LogicalAncestorNode is invalid in conjunction with a binding source.");
        if (target is ILogical)
            return target;
        if (anchor is ILogical)
            return anchor;
        throw new InvalidOperationException("Cannot find an ILogical to get a logical ancestor.");
    }

    public override bool ShouldLogErrors(object target)
    {
        return target is ILogical logical && logical.IsAttachedToLogicalTree;
    }

    protected override void OnSourceChanged(object? source, Exception? dataValidationError)
    {
        if (!ValidateNonNullSource(source))
            return;

View on GitHub (pinned to 11c5427268)

Solutions

  1. Remove the explicit Source so the logical-ancestor RelativeSource can traverse from the target.
  2. If you need a fixed source, drop the logical-ancestor relative source and bind the source object directly.

Example fix

// before
{Binding $parent[ItemsControl].Items, Source={StaticResource x}}
// after
{Binding $parent[ItemsControl].Items}
Defensive patterns

Strategy: validation

Validate before calling

// Logical-ancestor RelativeSource and explicit Source are mutually exclusive.
bool UsesLogicalAncestor(Binding b) =>
    b.RelativeSource is RelativeSource rs && rs.Mode == RelativeSourceMode.FindAncestor;

if (UsesLogicalAncestor(binding) && binding.Source is not null)
    throw new InvalidOperationException("Cannot combine logical-ancestor RelativeSource with Source.");

Try / catch

try { target.Bind(prop, binding); }
catch (NotSupportedException ex) when (ex.Message.Contains("LogicalAncestorNode"))
{ /* drop Source or the relative source */ }

Prevention

When it happens

Trigger: Combining Binding.Source with a path that uses a logical-ancestor RelativeSource ($parent[...] or $self-relative), or specifying both a Source and RelativeSource in the same binding.

Common situations: Adding Source= to a control-template binding that already uses $parent; mixing ElementName/Source with RelativeSource in one binding descriptor.

Related errors


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