dotnet/wpf · critical · OutOfMemoryException

ERROR_NOT_ENOUGH_MEMORY (8) / ERROR_OUTOFMEMORY (14)

ERROR_NOT_ENOUGH_MEMORY (8) / ERROR_OUTOFMEMORY (14)

Error message

OutOfMemoryException

What it means

The Win32 error mapper throws OutOfMemoryException when GetLastError is 8 (ERROR_NOT_ENOUGH_MEMORY) or 14 (ERROR_OUTOFMEMORY). The underlying Win32 UI call failed because the system or the target process could not allocate memory, and the mapper converts that native condition into the .NET OutOfMemoryException.

Solutions

  1. Free memory / reduce memory pressure on both the client and the target process, then retry
  2. Look for leaks in long-running automation loops (cached elements, providers, handles never released)
  3. Restart the target application if its process is exhausted (common for 32-bit targets)
  4. Catch OutOfMemoryException from UIA calls and retry after a delay rather than crashing the harness

Example fix

// before
var result = NativeCall(hwnd); // native error 8/14 -> OutOfMemoryException
// after
try
{
    var result = NativeCall(hwnd);
}
catch (OutOfMemoryException)
{
    GC.Collect();
    Thread.Sleep(500); // allow target process to recover
    result = NativeCall(hwnd); // retry
}
Defensive patterns

Strategy: retry

Validate before calling

// Check available memory before heavy automation runs:
var gc = GC.GetGCMemoryInfo();
if (gc.MemoryLoadBytes > threshold) { FreeResources(); }

Try / catch

for (int i = 0; i < 3; i++) { try { return NativeCall(hwnd); } catch (OutOfMemoryException) { Thread.Sleep(1000); GC.Collect(); } } throw;

Prevention

When it happens

Trigger: Win32 accessibility/window calls made by proxies (SendMessage, GetWindowLong-style calls, etc.) failing with native error 8 or 14 — system-wide or per-process memory exhaustion.

Common situations: Automating very large apps or desktops under memory pressure; target process hitting its address-space limit (32-bit processes); leaky automation loops that never release elements.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/3562ed301b40420b. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/Misc.cs:1691

                case 1400:  // 1400 ERROR_INVALID_WINDOW_HANDLE     Invalid window handle.
                case 1401:  // 1401 ERROR_INVALID_MENU_HANDLE       Invalid menu handle.
                case 1402:  // 1402 ERROR_INVALID_CURSOR_HANDLE     Invalid cursor handle.
                case 1403:  // 1403 ERROR_INVALID_ACCEL_HANDLE      Invalid accelerator table handle.
                case 1404:  // 1404 ERROR_INVALID_HOOK_HANDLE       Invalid hook handle.
                case 1405:  // 1405 ERROR_INVALID_DWP_HANDLE        Invalid handle to a multiple-window position structure.
                case 1406:  // 1406 ERROR_TLW_WITH_WSCHILD          Cannot create a top-level child window.
                case 1407:  // 1407 ERROR_CANNOT_FIND_WND_CLASS     Cannot find window class.
                case 1408:  // 1408 ERROR_WINDOW_OF_OTHER_THREAD    Invalid window; it belongs to other thread.
                    throw new ElementNotAvailableException();

                // We're getting this in AMD64 when calling RealGetWindowClass; adding this code
                // to allow the DRTs to pass while we continue investigation.
                case 87:    //   87 ERROR_INVALID_PARAMETER
                    throw new ElementNotAvailableException();

                case 8:     //    8 ERROR_NOT_ENOUGH_MEMORY         Not enough storage is available to process this command.
                case 14:    //   14 ERROR_OUTOFMEMORY               Not enough storage is available to complete this operation.
                    throw new OutOfMemoryException();

                case 998:   //  998 ERROR_NOACCESS                  Invalid access to memory location.
                case 5:     //    5 ERROR_ACCESS_DENIED
                    throw new InvalidOperationException();

                case 121:   //  121 ERROR_SEM_TIMEOUT               The semaphore timeout period has expired.
                case 258:   //  258 WAIT_TIMEOUT                    The wait operation timed out.
                case 1053:  // 1053 ERROR_SERVICE_REQUEST_TIMEOUT   The service did not respond to the start or control request in a timely fashion.
                case 1460:  // 1460 ERROR_TIMEOUT                   This operation returned because the timeout period expired.
                    throw new TimeoutException();

                default:
                    // Not sure how to map the reset of the error codes so throw generic Win32Exception.
                    throw new Win32Exception(errorCode);
            }
        }

        internal static bool UnhookWinEvent(IntPtr winEventHook)

View on GitHub (pinned to 81131a70a4)