dotnet/wpf · warning · System.Windows.Automation.ElementNotAvailableException
ElementNotAvailableException
Error message
ElementNotAvailableException
What it means
ElementNotAvailableException is the UI Automation proxy signal that the underlying Windows element has vanished or is no longer accessible. In WindowsMenu.GetHierarchyParent, the code asks the target hwnd for its menu handle (HmenuFromHwnd); when the OS returns IntPtr.Zero the menu no longer exists (the window was closed, destroyed, or never had a menu), so the proxy throws because it cannot compute a hierarchy parent for a dead element.
Solutions
- Re-fetch the element instead of using stale references: after any window close/menu rebuild, find the element again via AutomationElement.RootElement.FindFirst rather than walking from the old node.
- Wrap tree-walk calls (TreeWalker.GetParent/GetFirstChild) in try/catch for ElementNotAvailableException and treat the element as gone.
- Use FindAll/FindFirst with a TreeScope query instead of manual walker traversal; UIA core handles vanished elements more gracefully there.
- Ensure the automation target window is fully initialized and still alive before walking its menu (check AutomationElement.IsOffscreen / NativeWindowHandle and process HasExited).
Example fix
// before
AutomationElement parent = TreeWalker.ControlViewWalker.GetParent(menuElement);
// after
AutomationElement parent;
try
{
parent = TreeWalker.ControlViewWalker.GetParent(menuElement);
}
catch (ElementNotAvailableException)
{
parent = null; // window/menu closed; re-find element if needed
} Defensive patterns
Strategy: try-catch
Validate before calling
// before walking, check element is still alive
if (menuElement == null || (bool)menuElement.GetCurrentPropertyValue(AutomationElement.IsOffscreenProperty))
return null;
var hwnd = (IntPtr)menuElement.GetCurrentPropertyValue(AutomationElement.NativeWindowHandleProperty);
if (hwnd == IntPtr.Zero) return null; Type guard
static bool IsAlive(AutomationElement el)
{
try { var _ = el.Current.Name; return true; }
catch (ElementNotAvailableException) { return false; }
} Try / catch
try
{
parent = TreeWalker.ControlViewWalker.GetParent(menuElement);
}
catch (ElementNotAvailableException)
{
parent = null; // stale element; re-find via FindFirst if needed
} Prevention
- Re-find elements after window close or menu rebuild instead of walking from cached nodes
- Catch ElementNotAvailableException on every TreeWalker traversal step
- Verify the target process/window still exists before automation
- Prefer FindFirst/FindAll queries over manual walker traversal
When it happens
Trigger: Calling AutomationElement.TreeWalker (RawViewWalker/ControlViewWalker) GetParent/GetFirstChild on a WindowsMenu proxy whose hwnd's menu handle has become zero — typically because the window's menu was destroyed or the window closed between the element being found and the parent being resolved. Reached via callers WindowsMenu, FixMDIMenuType, and MenuEvents during tree walks and MDI menu restructuring.
Common situations: UIA clients walking menus of apps being closed or resized; MDI applications whose menu bar is rebuilt/replaced while automation is traversing it; tests that hold AutomationElement references across window close; timing races where the element is cached after the native menu is gone.
Related errors
- ElementNotAvailableException
- ' ' is not a valid value for this control.
- E_OUTOFMEMORY
- Element is not enabled.
- Element is not enabled.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/a4c093d0318214d4.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WindowsMenu.cs:535
System.Diagnostics.Debug.WriteLine(sb.ToString());
#endif
return result;
}
// Return menuItem object which is a hierarchical parent of the given menu (specified via hwnd)
// return NULL in the case when menu does not have a parent (e.g. Context menu)
// NOTE: this method should not be called for the menuItem that lives on the System or Menubar
internal static MenuItem GetHierarchyParent(IntPtr hwnd)
{
int ownerMenuItemPos = -1;
IntPtr menuParent = IntPtr.Zero;
IntPtr hwndParent = IntPtr.Zero;
IntPtr menu = HmenuFromHwnd(hwnd);
if (menu == IntPtr.Zero)
{
throw new ElementNotAvailableException();
}
MenuType currentType = GetSubMenuType(hwnd, menu);
MenuType parentType = MenuType.Toplevel;
if (currentType == MenuType.Submenu)
{
if (!GetSubMenuParent(hwnd, out menuParent, out hwndParent, out ownerMenuItemPos, out parentType))
{
return null;
}
ProxyFragment parent = null;
if (parentType == MenuType.Toplevel)
{
// Top Level Menu.
// We need to have the parenthood defined in the same way as if it was done
// from the non client area code.
View on GitHub (pinned to 81131a70a4)