{"record":{"id":"d428c1c28fe2e033","repo":"AvaloniaUI/Avalonia","slug":"cannot-find-an-ilogical-to-get-a-logical-ancestor","errorCode":null,"errorMessage":"Cannot find an ILogical to get a logical ancestor.","messagePattern":"Cannot find an ILogical to get a logical ancestor\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Data/Core/ExpressionNodes/LogicalAncestorElementNode.cs","lineNumber":51,"sourceCode":"            }\n\n            if (_ancestorLevel > 0)\n                builder.Append(_ancestorLevel);\n\n            builder.Append(']');\n        }\n    }\n\n    public override object? SelectSource(object? source, object target, object? anchor)\n    {\n        if (source != AvaloniaProperty.UnsetValue)\n            throw new NotSupportedException(\n                \"LogicalAncestorNode is invalid in conjunction with a binding source.\");\n        if (target is ILogical)\n            return target;\n        if (anchor is ILogical)\n            return anchor;\n        throw new InvalidOperationException(\"Cannot find an ILogical to get a logical ancestor.\");\n    }\n\n    public override bool ShouldLogErrors(object target)\n    {\n        return target is ILogical logical && logical.IsAttachedToLogicalTree;\n    }\n\n    protected override void OnSourceChanged(object? source, Exception? dataValidationError)\n    {\n        if (!ValidateNonNullSource(source))\n            return;\n\n        if (source is ILogical logical)\n        {\n            var locator = ControlLocator.Track(logical, _ancestorLevel, _ancestorType);\n            _subscription = locator.Subscribe(TrackedControlChanged);\n        }\n    }","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Data/Core/ExpressionNodes/LogicalAncestorElementNode.cs#L33-L69","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the binding target is an ILogical (a control/logical element) attached to the logical tree.","Apply the binding after the element is attached (e.g. in OnAttachedToLogicalTree or Loaded).","If you need a visual ancestor instead, use the visual-ancestor relative source."],"exampleFix":"// before - applied to non-ILogical or before attachment\nnode.Bind(..., new Binding(\"$parent[ItemsControl]\"));\n// after - ensure target is a logical element and attach first\ncontrol.Bind(..., new Binding(\"$parent[ItemsControl]\")); // in OnAttached","handlingStrategy":"validation","validationCode":"// Logical-ancestor bindings require an ILogical target.\nif (target is not ILogical)\n    throw new InvalidOperationException(\"Target is not in the logical tree; cannot resolve a logical ancestor.\");","typeGuard":"static bool IsInLogicalTree(object o) => o is ILogical l && l.IsAttachedToLogicalTree;","tryCatchPattern":"try { target.Bind(prop, binding); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ILogical\"))\n{ /* defer until attached, or use a visual ancestor source */ }","preventionTips":["Apply logical-ancestor bindings after the element joins the logical tree.","Confirm the target implements ILogical before binding.","Choose logical vs visual ancestor source deliberately."],"tags":["data-binding","relative-source","logical-tree","ancestor"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}