Back

Solucionar Error: 'listen EADDRINUSE: address already in use' en Node.js

Solucionar Error: 'listen EADDRINUSE: address already in use' en Node.js

El temido error EADDRINUSE aparece cuando menos lo esperas. Estás listo para iniciar tu servidor Node.js, pero en lugar de una aplicación en ejecución, obtienes: Error: listen EADDRINUSE: address already in use :::3000. Este error EADDRINUSE de Node.js significa que otro proceso ya está usando el puerto al que intentas conectarte. Aquí te mostramos cómo identificar y solucionar este conflicto de puertos en Node.js rápidamente.

Puntos Clave

  • El error EADDRINUSE ocurre cuando un puerto ya está ocupado por otro proceso
  • Usa lsof en macOS/Linux o netstat en Windows para identificar el proceso que bloquea
  • Termina el proceso usando su PID o implementa manejadores de cierre elegante
  • Previene conflictos futuros con selección dinámica de puertos y manejo apropiado de señales

¿Qué Causa el Error EADDRINUSE?

El error listen EADDRINUSE ocurre cuando tu aplicación Node.js intenta conectarse a un puerto que ya está ocupado. Los culpables comunes incluyen:

  • Una instancia previa de tu servidor aún en ejecución
  • Otra aplicación usando el mismo puerto
  • Procesos zombis de aplicaciones Node.js que fallaron
  • Herramientas de recarga en caliente como nodemon que no limpian correctamente
  • Terminales integradas de IDEs que mantienen procesos vivos

Cómo Encontrar Qué Proceso Está Usando el Puerto

Antes de poder liberar el puerto ocupado, necesitas identificar qué lo está usando. Los comandos difieren según el sistema operativo.

macOS y Linux

Usa lsof para encontrar el proceso:

lsof -i :3000

Esto devuelve detalles del proceso incluyendo el PID (ID del Proceso):

COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node     12345   you   11u  IPv6 0xac745b2749fd2be3      0t0  TCP *:3000 (LISTEN)

Windows

Usa netstat para identificar el proceso:

netstat -ano | findstr :3000

La salida muestra el PID en la última columna:

TCP    0.0.0.0:3000    0.0.0.0:0    LISTENING    12345

Cómo Terminar el Proceso y Liberar el Puerto

Una vez que tengas el PID, puedes terminar el proceso para liberar el puerto.

Soluciones para macOS y Linux

Comando rápido de una línea:

lsof -ti:3000 | xargs kill -9

Enfoque manual:

kill -15 12345  # Cierre elegante (preferido)
kill -9 12345   # Forzar terminación si -15 no funciona

Alternativa usando fuser:

sudo fuser -k 3000/tcp

Soluciones para Windows

Símbolo del sistema:

taskkill /PID 12345 /F

PowerShell:

Stop-Process -Id 12345 -Force

Método GUI: Abre el Administrador de Tareas (Ctrl+Shift+Esc), encuentra el proceso Node.js y finalízalo.

Prevenir Futuros Conflictos de Puertos

Implementar Cierre Elegante

Agrega manejadores de limpieza apropiados a tu servidor Node.js para prevenir errores de puerto:

const server = app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

// Handle termination signals
process.on('SIGTERM', () => {
  server.close(() => {
    console.log('Server closed gracefully');
    process.exit(0);
  });
});

process.on('SIGINT', () => {
  server.close(() => {
    console.log('Server closed gracefully');
    process.exit(0);
  });
});

Usar Selección Dinámica de Puertos

Evita codificar puertos de forma fija. Usa variables de entorno o encuentra un puerto disponible automáticamente:

const PORT = process.env.PORT || 3000;

// Or check port availability before binding
const net = require('net');

function getAvailablePort(startPort) {
  return new Promise((resolve) => {
    const server = net.createServer();
    server.listen(startPort, () => {
      const port = server.address().port;
      server.close(() => resolve(port));
    });
    server.on('error', () => {
      getAvailablePort(startPort + 1).then(resolve);
    });
  });
}

Manejar el Error Programáticamente

Captura el error y responde apropiadamente:

server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.error(`Port ${PORT} is already in use`);
    // Try another port or exit gracefully
    process.exit(1);
  }
});

Escenarios Comunes y Soluciones Rápidas

Nodemon No Libera los Puertos

Si usas nodemon, asegúrate de detenerlo con Ctrl+C, no con Ctrl+Z. Este último suspende el proceso sin liberar el puerto.

Conflictos con Contenedores Docker

Verifica los contenedores en ejecución:

docker ps
docker stop <container_id>

Problemas con la Terminal de VS Code

Cierra todas las terminales integradas antes de reiniciar tu servidor. A veces VS Code mantiene procesos vivos en segundo plano.

Múltiples Instancias de Servidor en el Código

Asegúrate de no estar llamando app.listen() múltiples veces en tu código base. Este error común desencadena el error address already in use inmediatamente.

Conclusión

El error EADDRINUSE de Node.js es frustrante pero fácil de solucionar. Encuentra el proceso usando tu puerto con lsof o netstat, termínalo e implementa manejadores de cierre apropiados para prevenir futuras ocurrencias. Recuerda: cierres elegantes con manejadores de señales y selección dinámica de puertos te ahorrarán tener que lidiar repetidamente con este error de puerto del servidor Node.js.

Preguntas Frecuentes

Sí, puedes implementar cambio automático de puerto capturando el error EADDRINUSE e intentando con el siguiente puerto disponible. Usa una función recursiva o bucle para probar puertos secuencialmente hasta encontrar uno abierto, o usa bibliotecas como portfinder que manejan esto automáticamente.

Cerrar una ventana de terminal no siempre termina los procesos en ejecución. Los procesos en segundo plano, especialmente aquellos iniciados con nohup o como servicios, continúan ejecutándose. Siempre usa comandos de terminación apropiados como Ctrl+C o mata explícitamente el proceso usando su PID para asegurar que el puerto se libere.

Usar kill -9 fuerza la terminación inmediata sin permitir limpieza, lo que puede causar pérdida o corrupción de datos. Siempre intenta primero kill -15 para un cierre elegante. Reserva kill -9 para procesos que no responden. Implementa manejadores de señales apropiados en tu código para asegurar cierres limpios.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay