dotnet/wpf · warning · ElementNotAvailableException
new ElementNotAvailableException(e)
Error message
new ElementNotAvailableException(e)
What it means
Inside HandleIAccessibleException, a COMException with E_OUTOFMEMORY (or equivalent) is deliberately translated to ElementNotAvailableException with the original as inner exception. OLEACC proxies report out-of-memory for non-critical reasons — notably the treeview proxy when the target HWND no longer exists and shared memory cannot be allocated in the target process — so the provider reinterprets it as 'element not available'.
Solutions
- Treat this as ElementNotAvailableException on the caller side: re-find the element and retry
- Detect and wait for target window recreation (e.g. re-find by WindowPattern / wait for WindowOpenedEvent) instead of using the stale reference
- Verify the target application/HWND is still alive (IsWindow / UIA not-visible check) before operating on proxied elements
- Batch reads with CacheRequest to minimize the number of cross-process proxy calls during unstable UI states
Example fix
// before var item = FindTreeItem(); item.Select(); // may throw ElementNotAvailable (OOM proxy) after tree rebuild // after var item = WaitForElementByAutomationId(id, timeout: 5000); if (item != null) item.Select();
Defensive patterns
Strategy: retry
Validate before calling
if (!IsWindowStillAlive(element)) return null; // e.g. compare RuntimeId / use WindowPattern
bool IsWindowStillAlive(AutomationElement e) {
try { return !e.Current.IsOffscreen || e.Current.BoundingRectangle != Rect.Empty; }
catch (ElementNotAvailableException) { return false; }
} Type guard
static bool TryGet<T>(Func<T> f, out T value) {
try { value = f(); return true; }
catch (ElementNotAvailableException) { value = default; return false; }
} Try / catch
for (int attempt = 0; attempt < 3; attempt++) {
try { DoWork(element); break; }
catch (ElementNotAvailableException ex)
when (ex.InnerException is COMException ce && ce.HResult == unchecked((int)0x8007000E)) {
element = FindElementAgain(); // OOM proxy => HWND likely gone; re-find
}
} Prevention
- Wait for window recreation events before re-driving treeview-style controls
- Avoid enumerating trees while the target window is being rebuilt
- Use CacheRequest to reduce proxy round-trips
- Check target process/HWND liveness before calls
When it happens
Trigger: Calling into an IAccessible whose OLEACC proxy fails to allocate shared memory in the target process because GetWindowThreadProcessId fails — i.e. the target HWND died; any IAccessible call raising a COMException with OOM HRESULT, converted before the critical-exception check (OOM would otherwise be treated as critical).
Common situations: Treeview controls being destroyed/recreated while UIA enumerates their proxy; target window handle invalidated between discovery and call; memory pressure in the target process surfacing as OOM HRESULTs during cross-process MSAA calls.
Related errors
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/ea803a3ba94af587.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/Accessible.cs:1293
rect.right += rect.left; // convert width to right
rect.bottom += rect.top; // convert height to bottom
return rect;
}
// converts the exception into a more appropriate one and throws it,
// or returns false indicating the caller should assume a default result
// or returns true indicating the caller should rethrow the exception.
private static bool HandleIAccessibleException(Exception e)
{
if (e is OutOfMemoryException)
{
// Some OLEACC proxies produce out-of-memory for non-critical reasons:
// notably, the treeview proxy will raise this if the target HWND no longer exists,
// GetWindowThreadProcessID fails and it therefore won't be able to allocate shared
// memory in the target process, so it incorrectly assumes OOM.
// (Need to check this before Misc.IsCriticalException, since it includes OOM as critical.)
throw new ElementNotAvailableException(e);
}
if (e is NullReferenceException)
{
// Media Player and some other badly-implemented IAccessibles can return the correponding
// COM error code (E_POINTER). This does not actually indicate a null dereference in this
// process.
throw new ElementNotAvailableException(e);
}
if (Misc.IsCriticalException(e))
{
return true;
}
COMException comException = e as COMException;
if (e is NotImplementedException)View on GitHub (pinned to 81131a70a4)