01
Exit code 137 não é vazamento: duas mortes com sintomas diferentes
Existem duas maneiras de um processo Node morrer por memória, e elas deixam rastros opostos. Quando o heap do V8 chega ao próprio limite e o coletor não consegue liberar espaço, o Node escreve "FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory" no stderr, imprime um resumo dos espaços do heap e encerra com um código de saída próprio. É uma morte que o processo vê chegando: dá para gerar um heap snapshot perto do limite, dá para registrar o estado. Quando o RSS do processo passa do limite do cgroup, é o kernel que decide, de fora, com SIGKILL. Não há sinal a tratar, não há handler que rode, não há linha de log. O processo simplesmente para de existir, e a única evidência é o exit code 137 no orquestrador e uma linha no dmesg do nó.
| Sintoma | Quem decidiu | O que o processo viu | Causa mais provável |
|---|---|---|---|
| FATAL ERROR: Reached heap limit no stderr | O V8, ao falhar uma alocação no heap | Tudo: o erro sai no log com estatísticas dos espaços | Vazamento de objetos JavaScript ou heap configurado pequeno demais para a carga |
| OOMKilled, exit code 137, nenhuma linha final no log | O kernel, ao comparar o RSS com memory.max | Nada: SIGKILL não é entregue ao processo | Heap dimensionado acima do limite do contêiner, ou memória fora do heap sem teto |
| ENOMEM em chamadas nativas, Buffer.alloc lançando erro | O alocador, ao pedir memória ao sistema | Uma exceção na chamada que falhou | Limite de memória virtual ou alocação única grande demais; raro em contêiner |
A segunda linha é o caso deste artigo. E o teste que diferencia os dois é simples: no gráfico de heapUsed, um vazamento aparece como vales que sobem ao longo das horas, porque a cada coleta completa sobra mais memória viva. Um processo mal dimensionado mostra vales estáveis e picos altos, porque o lixo acumula até onde o V8 permite, e o V8 permite mais do que o cgroup. Se os vales não sobem e o processo morreu mesmo assim, não adianta procurar o array que cresce. O problema está na configuração.