AvaloniaUI/Avalonia · error · InvalidOperationException

Cannot find an ILogical to get a logical ancestor.

Error message

Cannot find an ILogical to get a logical ancestor.

What it means

LogicalAncestorElementNode.SelectSource throws InvalidOperationException when neither target nor anchor implements ILogical. Logical-ancestor traversal requires a starting point in the logical tree; without an ILogical there is nothing to walk up from.

Source

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

            }

            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;

        if (source is ILogical logical)
        {
            var locator = ControlLocator.Track(logical, _ancestorLevel, _ancestorType);
            _subscription = locator.Subscribe(TrackedControlChanged);
        }
    }

View on GitHub (pinned to 11c5427268)

Solutions

  1. Ensure the binding target is an ILogical (a control/logical element) attached to the logical tree.
  2. Apply the binding after the element is attached (e.g. in OnAttachedToLogicalTree or Loaded).
  3. If you need a visual ancestor instead, use the visual-ancestor relative source.

Example fix

// before - applied to non-ILogical or before attachment
node.Bind(..., new Binding("$parent[ItemsControl]"));
// after - ensure target is a logical element and attach first
control.Bind(..., new Binding("$parent[ItemsControl]")); // in OnAttached
Defensive patterns

Strategy: validation

Validate before calling

// Logical-ancestor bindings require an ILogical target.
if (target is not ILogical)
    throw new InvalidOperationException("Target is not in the logical tree; cannot resolve a logical ancestor.");

Type guard

static bool IsInLogicalTree(object o) => o is ILogical l && l.IsAttachedToLogicalTree;

Try / catch

try { target.Bind(prop, binding); }
catch (InvalidOperationException ex) when (ex.Message.Contains("ILogical"))
{ /* defer until attached, or use a visual ancestor source */ }

Prevention

When it happens

Trigger: Using a $parent logical-ancestor binding on an object that does not participate in the logical tree, or before the target is attached to the logical tree.

Common situations: Applying a logical-ancestor binding to a plain object/non-visual; binding too early in the element lifecycle (before logical-tree attachment); using logical-ancestor syntax in a context where only a visual exists.

Related errors


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