TPTito Pinardo Gutiérrez
← Artículos
English

2.104 Chrome sin cabeza huérfanos: una fuga de memoria con Puppeteer

El contenedor de las automatizaciones estaba a punto de quedarse sin memoria. n8n solo usaba 264 MB. Lo demás eran 2.104 procesos de Chrome sin cabeza acumulados durante 22 días.

  • JavaScript / TypeScript
  • Docker
  • Linux (Debian, Alpine, Arch)

Síntoma

La monitorización avisó de que el contenedor de n8n tenía 31 GB usados de 32 y 154 MB libres. El proceso de n8n usaba 264 MB.

ps aux --sort=-%mem | head
# → 2.104 procesos …/chrome-linux64/chrome, el más antiguo de hacía 22 días

Causa

Una pequeña API con Puppeteer abre un navegador sin cabeza para los flujos de n8n y lo reutiliza. En los catch de sus rutas, ante cualquier error (un timeout, un selector que no aparece), el código hacía browser = null sin llamar a browser.close().

Eso descarta la referencia de JavaScript, pero el proceso de Chrome del sistema sigue vivo para siempre. Cada fallo de la web de origen dejaba un navegador más.

// antes
} catch (e) { browser = null; throw e; }

// después
async function closeBrowser() {
  if (browser) await browser.close().catch(() => {});
  browser = null;
}
} catch (e) { await closeBrowser(); throw e; }

Resultado

  • Matar los huérfanos liberó unos 28 GB al instante.
  • Desde el arreglo, aunque la web de origen falle una y otra vez, el recuento de procesos de Chrome se queda en cero.
  • El fichero de la API está montado como volumen: se pudo arreglar con un reinicio del contenedor, sin reconstruir la imagen.