dotnet/wpf · warning · ElementNotAvailableException
Element no longer available.
Error message
Element no longer available.
What it means
ElementNotAvailableException ('Element no longer available.') is thrown by the WindowsButton proxy's RaiseEvents path when the underlying Win32 window handle (hwnd) is no longer a valid window (IsWindow returns false). UIA elements are proxies over live HWNDs; once the target window is destroyed, the proxy can no longer raise events on it. The library throws rather than silently dropping the event so clients know the element went stale.
Solutions
- Wrap event-handler bodies and any use of stale AutomationElement references in try-catch for ElementNotAvailableException and ignore the event.
- Re-resolve the element from the desktop via a fresh FindFirst/FindAll instead of reusing cached references across UI changes.
- Use AutomationElement caching (CacheRequest) with events and guard property reads so stale elements fail fast without cascading.
- Serialize UI interactions with the app's lifecycle so the client stops interacting before controls are disposed.
Example fix
// before
AutomationEventHandler handler = (src, e) =>
{
var button = (WindowsButtonProxy)src;
button.Invoke();
};
// after
AutomationEventHandler handler = (src, e) =>
{
try
{
var button = (WindowsButtonProxy)src;
button.Invoke();
}
catch (ElementNotAvailableException)
{
// element's window was destroyed; re-find it
var fresh = desktop.FindFirst(TreeScope.Descendants, nameCondition);
fresh?.Invoke();
}
}; Defensive patterns
Strategy: try-catch
Validate before calling
// C# (UIA client)
// There is no public IsWindow check; guard by re-resolving the element
var fresh = AutomationElement.RootElement.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.NameProperty, buttonName));
bool usable = fresh != null; Type guard
static bool IsAlive(AutomationElement e)
{
try { var _ = e.Current.Name; return true; }
catch (ElementNotAvailableException) { return false; }
} Try / catch
try
{
// interact with element / handle its event payload
}
catch (ElementNotAvailableException)
{
// window destroyed; re-find or skip
} Prevention
- Never cache AutomationElement references across UI lifecycles; re-resolve after structure changes.
- Wrap every event handler and cached-element access in ElementNotAvailableException handling.
- Use a CacheRequest so property reads fail gracefully on stale elements.
- Synchronize test steps with the app under test so elements are not disposed mid-operation.
When it happens
Trigger: An event handler (AutomationEventHandler / property-changed / structure-changed callback) fires for a WindowsButton whose hwnd has been destroyed; RaiseEvents validates with UnsafeNativeMethods.IsWindow(hwnd) and throws ElementNotAvailableException on failure.
Common situations: Desktop apps closing dialogs or disposing controls while a UIA client holds cached references; race conditions where a button is removed or re-created between event registration and delivery; automated UI tests where the app under test crashes or exits mid-run.
Related errors
- ElementNotAvailableException
- new ElementNotAvailableException()
- E_OUTOFMEMORY
- Element no longer available.
- ElementNotAvailableException
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/e8a524a46ca360f8.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/WindowsButton.cs:153
catch (ElementNotAvailableException)
{
return null;
}
return new WindowsButton(hwnd, null, type, style, null);
}
// Static create method called by the event tracker system.
// WinEvents are thrown only when a notification has been set for a
// specific item. Create the item first and check for details afterward.
internal static void RaiseEvents (IntPtr hwnd, int eventId, object idProp, int idObject, int idChild)
{
if (idObject != NativeMethods.OBJID_VSCROLL && idObject != NativeMethods.OBJID_HSCROLL)
{
// Can not RaiseEvents on windows that are no longer available.
if (!UnsafeNativeMethods.IsWindow(hwnd))
{
throw new ElementNotAvailableException();
}
WindowsButton wtv = (WindowsButton)Create(hwnd, 0);
// Create can return null if we don't know what kind of button this is
if (wtv == null)
{
return;
}
//Only one event is generated for the winforms button so no need to check the pressed state.
if (wtv._acc != null)
{
if (idProp == SelectionItemPattern.ElementSelectedEvent)
{
if (!wtv._acc.HasState(AccessibleState.Checked))
{
eventId = NativeMethods.EventObjectSelectionRemove;View on GitHub (pinned to 81131a70a4)