{"record":{"id":"fc71289f3722e61b","repo":"dotnet/wpf","slug":"elementnotavailableexception-msaanativeprovider","errorCode":null,"errorMessage":"ElementNotAvailableException","messagePattern":"ElementNotAvailableException","errorType":"exception","errorClass":"ElementNotAvailableException","httpStatus":null,"severity":"warning","filePath":"src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/MSAANativeProvider.cs","lineNumber":1029,"sourceCode":"                    // note: _controlType can stay null. in that case we'll try to figure it out each time.\n                    // if this is a performance problem we can add a separate boolean flag to indicate whether\n                    // we have computed the control type.\n                }\n\n                // return the cached value\n                return _controlType;\n            }\n        }\n\n        private Accessible GetParent()\n        {\n            // this should never be called on a root.\n            Debug.Assert(!IsRoot);\n\n            // we should never step up out of a \"window\". we should hit the root first.\n            if (_acc.Role == AccessibleRole.Window)\n            {\n                throw new ElementNotAvailableException();\n            }\n\n            Accessible parentAccessible = _acc.Parent;\n\n            // if we get a null parent (Accessible.Parent will return null for IAccessible's\n            // when we detect bad navigation) then we have no idea where we are. bail.\n            if (parentAccessible == null)\n            {\n                throw new ElementNotAvailableException();\n            }\n\n            return parentAccessible;\n        }\n\n\n        // The following classes are known to have bad IAccessible implementation (eg.\n        // overly complex structure or too many problems for the proxy to deal with).\n        // Note that while similar \"bad lists\" are used by UIACore and the proxy manager,","sourceCodeStart":1011,"sourceCodeEnd":1047,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/MSAANativeProvider.cs#L1011-L1047","documentation":"GetParent on an MSAA-backed element is only valid below a window boundary; if the element's accessible role is Window, walking up would escape the automation 'window', so the provider throws ElementNotAvailableException. The UIA element has become invalid for navigation (its parent is out of scope).","triggerScenarios":"Calling TreeWalker.RawViewWalker/ControlViewWalker GetParent (or the Parent property) on an element whose accessible Role == AccessibleRole.Window — i.e. asking for the parent of a window root that is not the UIA root element.","commonSituations":"Walking up from a top-level window or dialog expecting to reach the desktop element; cached tree walks done after UI restructuring where the former child now behaves as a window root; custom proxies reporting Window role unexpectedly.","solutions":["Stop the upward walk when the element's CurrentControlType is Window/Pane or when AutomationElement.RootElement is reached","Compare the element against AutomationElement.RootElement before requesting its parent","Re-walk from RootElement using FindFirst/FindAll instead of walking up from a stale element","Catch ElementNotAvailableException and treat it as 'reached the top of the scope' rather than a failure"],"exampleFix":"// before\nwhile (e != null) { Process(e); e = walker.GetParent(e); }\n// after\nwhile (e != null && !Equals(e, AutomationElement.RootElement))\n{\n    if ((int)e.GetCurrentPropertyValue(AutomationElement.ControlTypeProperty)\n        == ControlType.Window.Id) break; // window boundary: stop walking up\n    Process(e);\n    e = walker.GetParent(e);\n}","handlingStrategy":"try-catch","validationCode":"if (element == AutomationElement.RootElement || element.Current.ControlType == ControlType.Window) return null; // top of walk","typeGuard":"static bool IsWindowRoot(AutomationElement e) => e.Current.ControlType == ControlType.Window || e == AutomationElement.RootElement;","tryCatchPattern":"try { parent = walker.GetParent(element); }\ncatch (ElementNotAvailableException) { parent = null; /* reached window boundary */ }","preventionTips":["Stop upward walks at Window control type or RootElement","Avoid cached tree references after UI restructure","Re-resolve elements from the root after navigation changes"],"tags":["ui-automation","element-not-available","tree-walk"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}