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 
lsofen macOS/Linux onetstaten 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.
Discover how at OpenReplay.com.
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.