Solución integral al error 0x80070008 “Not enough memory resources” en Windows Server 2019

Cuando un sitio ASP.NET o un servicio Windows devuelve la excepción System.Runtime.InteropServices.COMException (0x80070008), el administrador suele pensar que falta RAM. Sin embargo, en Windows Server 2019 el mensaje “Not enough memory resources are available to process this command” casi siempre apunta a una crisis de memoria virtual, a un agotamiento del pool de kernel o a límites de direccionamiento en procesos de 32 bits. Este artículo desglosa las causas y ofrece una guía detallada para resolver el problema y evitar su reaparición.

Índice

Comprender el error “Not enough memory resources are available to process this command”

El código 0x80070008 está asociado a ERRORNOTENOUGH_MEMORY. Windows lo devuelve cuando no puede satisfacer una solicitud de memoria realizada por el proceso o por el propio kernel, aun cuando la RAM física parezca abundante. Las razones más frecuentes son:

  • Agotamiento del espacio de direcciones de usuario (2 GB por defecto en procesos x86, 4 GB con large address aware, 8 TB en x64).
  • Pool de memoria del kernel saturado (Paged Pool o Non‑Paged Pool).
  • Compromiso de memoria mayor que la suma “RAM + Pagefile”, debido a un archivo de paginación deshabilitado o demasiado pequeño.
  • Fugas de recursos: handles, GDI, objetos USER, heap nativo, etc.

Cómo se manifiesta en aplicaciones web e IIS

En un entorno ASP.NET alojado en IIS a menudo aparecen:

  • HTTP 500 con el código 0x80070008 en el registro de IIS.
  • Eventos Application Error y WAS en el Visor de eventos.
  • Fallos intermitentes coincidentes con picos de tráfico o tareas batch nocturnas.
  • Creación de process dumps si están habilitados en el Application Pool.

Pasos de corrección recomendados

PasoAcciónDetalles
Reparar archivos de sistemaDISM + SFC con privilegios de administradorDISM /Online /Cleanup-Image /ScanHealth DISM /Online /Cleanup-Image /RestoreHealth sfc /scannowReiniciar cuando finalice.
Aplicar actualizacionesInstalar los últimos parches de Windows y de la aplicaciónIncluye CU, SSU, .NET Framework, controladores y redistribuibles VC++.
Verificar arquitecturaAsegurar que IIS y la app sean 64 bitsDeshabilitar Enable 32‑Bit Applications en el Application Pool.
Revisar consumo de recursosTask Mgr, PerfMon, PoolMon, Process ExplorerMonitorizar Private Bytes, Pool Nonpaged Bytes, handles, objetos GDI/USER.
Ajustar el pagefileHabilitarlo y asignarlo en modo “sistema gestionado”Eliminando el pagefile se reduce el “commit limit” y aparecen errores 0x80070008.
Reciclado del Application PoolProgramar reciclados o fijar límites de memoriaPermite liberar recursos de procesos web de larga ejecución.
Actualizar dependencias externasControladores, componentes COM+, librerías nativasUna DLL antigua puede filtrar memoria en cada llamada COM y acabar agotándola.

Profundizando en los pools de memoria del kernel

Windows divide su memoria de kernel en los pools Paged y Non‑Paged. Cuando un controlador o componente del sistema solicita memoria con ExAllocatePool, esta proviene de dichos pools. Si un bug impide que se libere, los contadores Pool Paged Bytes o Pool Nonpaged Bytes irán creciendo hasta alcanzar su techo —diferente según SKU y RAM instalada—. Llegados al límite, cualquier operación que requiera más bytes devolverá STATUSINSUFFICIENTRESOURCES, que el subsistema COM traduce a 0x80070008.

Indicadores críticos en Performance Monitor

  • Memory\Available MBytes debe permanecer holgado. Si baja de 100 MB, el sistema canjea RAM por pagefile.
  • Memory\Committed Bytes próximo a Memory\Commit Limit revela carencia de paginación.
  • Memory\Pool Nonpaged Bytes superior a 1.5 GB en Server 2019 suele indicar fuga.
  • Process(*)\Private Bytes ayuda a detectar procesos que crecen sin parar.

Diagnóstico con herramientas avanzadas

PoolMon

Ejecutar poolmon.exe /b (parte del SDK/WDK) muestra los tag que consumen Non‑Paged Pool. Una entrada que crece sin soltar memoria a lo largo del tiempo apunta al controlador culpable. Revisar las columnas Bytes y Alloc tras 15‑30 minutos de carga real.

Process Explorer

En la vista inferior seleccionar View > System Information para ver los pools de kernel en tiempo real. Hacer clic derecho en Private Bytes de w3wp.exe para trazar su comportamiento histórico.

DebugDiag 2.x

Instalarlo y elegir la regla “A memory and handle leak in a native process”. Configurar w3wp como objetivo. Cuando la fuga supere el umbral pre­definido se generará un user‑mode dump. Abrir el DMP con DebugDiag Analysis generará un informe HTML que señala clases CLR o funciones nativas monopolizando memoria.

WinDbg / Sos / ClrMD

Para fugas administradas cargar !eestat, !dumpheap –stat y !dumpheap –type; para nativas usar !heap –s y !poolused 2. Si un tag de pool aparece millonario, ejecutar !poolfind puede revelar el controlador exacto.

Optimización de configuración IIS y .NET

  • Asignar maxConcurrentRequestsPerCPU y maxConcurrentThreadsPerCPU solo cuando se haya medido contención.
  • Deshabilitar Load User Profile en el Application Pool si la aplicación no lo necesita (reduce objetos de kernel).
  • Activar Server Garbage Collection (<gcServer enabled="true"/>) en servidores multinúcleo; combina heaps y disminuye fragmentación.
  • Modificar gcAllowVeryLargeObjects si se manipulan blobs > 2 GB en arrays.
  • Aplicar recortes de stack con ThreadPool.SetMinThreads para limitar el recuento máximo de hilos.

Buenas prácticas preventivas

La mejor defensa contra 0x80070008 es la higiene operativa:

  1. Monitorización continua con Azure Monitor, System Center OM o Grafana. Configurar alertas para “Pool Nonpaged Bytes” > 1 GB y “Committed Bytes” > 90 %.
  2. Revisión de código: cerrar IDisposable, liberar objetos COM con Marshal.ReleaseComObject, no almacenar grandes arrays estáticos.
  3. Pruebas de estrés: emplear Azure Load Testing, JMeter o K6 para replicar picos de producción.
  4. Centinel de actualizaciones: mantener al día .NET, drivers y firmware (BIOS/iLO) para evitar fugas en minipuertos.
  5. Documentar baseline de contadores tras cada release para detectar desviaciones.

Preguntas frecuentes

¿Puedo simplemente aumentar la RAM física?

Añadir RAM puede retrasar el síntoma, pero no resuelve fugas de pool ni procesos de 32 bits; el espacio de direcciones y el pool kernel tienen límites independientes de la RAM.
¿Deshabilitar el antivirus ayuda?

Un motor AV puede consumir Non‑Paged Pool; pruebe con exclusiones o una versión actual antes de deshabilitarlo. Desactivar protección no es una solución permanente.
¿Afecta el recuento de CPUs virtuales en Hyper‑V?

Sí. Cada vCPU reserva estructuras en Non‑Paged Pool. Máquinas con muchos núcleos y baja carga real pueden beneficiarse de reducir vCPUs.
¿Es lo mismo que el error 0xC0000017?

No. 0xC0000017 es STATUSNOMEMORY y aparece al crear un proceso o reservar memoria en modo kernel. Ambos implican presión de memoria, pero tienen códigos y escenarios distintos.

Conclusión

El error 0x80070008 en Windows Server 2019 no significa falta de memoria física; es un aviso de que alguna parte del sistema —proceso de 32 bits, driver defectuoso o pagefile insuficiente— agotó su límite de memoria virtual. Siguiendo los pasos de esta guía, identificará la causa, restaurará la estabilidad y obtendrá una plataforma preparada para soportar aumentos de carga futuros.

Índice