dotnet/wpf · warning · ElementNotAvailableException
E_UNEXPECTED
E_UNEXPECTED
Error message
ElementNotAvailableException(e)
What it means
The IAccessible server returned E_UNEXPECTED and the provider translates it into ElementNotAvailableException. Per the code comment this means the MSAA server was released unexpectedly but still has pending events; if execution is inside one of the provider's event handlers it must be abandoned. It signals the accessible server object died mid-operation.
Solutions
- Catch ElementNotAvailableException in event handlers and exit the handler gracefully (the framework requires abandoning the context).
- Unregister event handlers (RemoveAutomationEventHandler) when the target window is closed rather than leaving them attached.
- Check whether the target application is crashing or leaking COM references; use AppVerifier/COM ref tracking if the server release is unexpected.
- Retry the operation after re-resolving the element tree; the element that owned the server is gone.
Example fix
// before
Automation.AddAutomationEventHandler(InvokePattern.InvokedEvent, win, TreeScope.Element,
(s, e) => Process(e.Source.Current.Name)); // server released -> E_UNEXPECTED crash out of handler
// after
Automation.AddAutomationEventHandler(InvokePattern.InvokedEvent, win, TreeScope.Element,
(s, e) =>
{
try { Process(e.Source.Current.Name); }
catch (ElementNotAvailableException) { /* server released; abandon handler */ }
}); Defensive patterns
Strategy: try-catch
Validate before calling
// Before relying on long-lived event subscriptions, confirm the target window is open: bool TargetAlive(Process p) => !p.HasExited && p.MainWindowHandle != IntPtr.Zero;
Try / catch
try
{
HandleEvent(e);
}
catch (ElementNotAvailableException)
{
// server released with pending events: abandon this handler invocation
return;
} Prevention
- Wrap all UIA event-handler bodies in try/catch for ElementNotAvailableException.
- Remove event handlers when the owning window closes instead of leaving them attached.
- Watch for target-app crashes or leaked COM references causing premature server release.
- Re-resolve elements after catching; the old backing IAccessible is permanently gone.
When it happens
Trigger: An Accessible-wrapped IAccessible call (property read, navigation, or an event handler callback on the provider) after the native server was released — e.g. the hosting window/control was destroyed while MSAA events were still being dispatched.
Common situations: Applications closing windows during active AutomationEventHandler/AutomationFocusChanged callbacks; UIA clients holding AutomationEventHandlers registered on short-lived windows; crash or fast exit of the target app during event dispatch.
Related errors
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/118d15b9575e9a3e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/Accessible.cs:1366
// GetWindowThreadProcessID fails and it therefore won't be able to allocate shared
// memory in the target process, so it incorrectly assumes OOM.
throw new ElementNotAvailableException(e);
case NativeMethods.E_INVALIDARG:
// One or more arguments were invalid. This error occurs when the caller attempts to identify
// a child object using an identifier that the server does not recognize. This error also results
// when a client attempts to identify a child object within an object that has no children.
throw new ArgumentException(SR.InvalidParameter);
case NativeMethods.E_ACCESSDENIED:
// This is returned when you call get_accValue to get the value of a password control.
throw new UnauthorizedAccessException();
case NativeMethods.E_UNEXPECTED:
// An IAccessible server has been released unexpectedly but still has pending events.
// If the current execution context is inside one of these event handlers it must be
// abandoned.
throw new ElementNotAvailableException(e);
default:
// we want to know when we get an exception we haven't seen before
Debug.Fail(string.Format(CultureInfo.CurrentCulture, "MsaaNativeProvider: IAccessible threw a COMException: {0}", e.Message));
break;
}
}
else if (e is InvalidCastException)
{
// sometimes Trident throws InvalidCastExceptions on elements from obsolete pages
throw new ElementNotAvailableException(e);
}
else if (e is BadImageFormatException)
{
// This control/window mostly has went away or is in the process of shutting down.
throw new ElementNotAvailableException(e);
}
elseView on GitHub (pinned to 81131a70a4)