Risolvere npm ERR! code EADDRINUSE: Address already in use

Soluzione Rapida

Se conosci il numero di porta che la tua applicazione sta cercando di utilizzare (ad esempio, porta 3000), esegui i seguenti comandi nel terminale per identificare e terminare il processo che la sta occupando.

Linux / macOS (Bash)

# 1. Trova il Process ID (PID) in esecuzione sulla porta 3000
lsof -i :3000

# Output tipico:
# COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
# node    12345 root   22u  IPv4 0x12345678      0t0  TCP *:3000 (LISTEN)

# 2. Termina il processo usando il PID trovato (es. 12345)
kill -9 12345

Terminazione rapida in una riga:

# Termina forzatamente qualsiasi processo sulla porta 3000
npx kill-port 3000

Windows (PowerShell)

# 1. Trova il PID in ascolto sulla porta 3000
Get-NetTCPConnection -LocalPort 3000

# 2. Ferma il processo usando il PID (OwningProcess)
Stop-Process -Id <PID> -Force

Perché accade questo errore

L’errore EADDRINUSE è l’acronimo di “Error Address In Use” (Errore Indirizzo In Uso). È un segnale a livello di sistema operativo che indica che un’applicazione sta tentando di associare (bind) un socket TCP/IP a una porta di rete che è già occupata da un altro processo attivo.

Nel contesto di Node.js, questo errore si verifica quasi esclusivamente durante l’inizializzazione del server HTTP (server.listen()). Quando la tua applicazione richiede al kernel di riservare una porta (es. 3000), il sistema controlla la tabella globale dei socket. Se quella combinazione IP:Porta è già assegnata, la richiesta viene respinta con il codice di errore EADDRINUSE.

Cause Comuni

  1. Processi Zombie: Un’istanza precedente del server Node.js non è stata chiusa correttamente (ad esempio dopo un crash o un Ctrl+C non gestito), lasciando il socket aperto in background.
  2. Esecuzione Multipla: Tentativo di avviare due istanze della stessa applicazione contemporaneamente (es. due terminali aperti sullo stesso progetto).
  3. Conflitto con Altri Servizi: Un altro servizio (come un database locale, Docker, o un’altra app) sta già utilizzando la porta richiesta.
  4. Race Condition nei Test: Esecuzione di suite di test in parallelo dove ogni worker tenta di avviare un server sulla stessa porta fissa.

Diagnostica Avanzata su Linux

Su sistemi Linux (Ubuntu, Debian, CentOS, ecc.), esistono strumenti potenti per ispezionare lo stato della rete.

1. Utilizzare lsof (List Open Files)

lsof è lo standard de facto per mappare file e socket ai processi.

# Sintassi: lsof -i :<PORTA>
sudo lsof -i :3000

Se il comando non restituisce nulla ma ricevi comunque l’errore, il processo potrebbe essere stato avviato da un altro utente (o root), motivo per cui sudo è spesso necessario.

2. Utilizzare netstat

Se lsof non è disponibile, netstat è una valida alternativa.

# -n: Indirizzi numerici
# -l: Solo socket in ascolto
# -p: Mostra PID/Nome programma
sudo netstat -nlp | grep :3000

3. Utilizzare fuser

Per identificare e terminare il processo in un colpo solo:

# Visualizza solo il PID
fuser 3000/tcp

# Termina il processo che occupa la porta (k = kill)
fuser -k 3000/tcp

Diagnostica Avanzata su macOS

macOS condivide molti strumenti con Linux ma con alcune differenze nei flag.

1. Utilizzare lsof

Il comando è simile a Linux, ma possiamo essere più specifici con i protocolli.

# Trova processi TCP in stato LISTEN sulla porta 3000
lsof -iTCP:3000 -sTCP:LISTEN

2. Monitoraggio Attività (GUI)

Se preferisci l’interfaccia grafica:

  1. Apri Monitoraggio Attività (Activity Monitor) tramite Spotlight.
  2. Vai alla scheda Rete o CPU.
  3. Cerca “node” nella barra di ricerca.
  4. Seleziona il processo e clicca sulla “X” in alto per forzare l’uscita.

Diagnostica Avanzata su Windows

Windows gestisce i socket in modo diverso rispetto ai sistemi Unix-like.

1. PowerShell (Metodo Consigliato)

PowerShell offre cmdlet nativi per la gestione della rete, eliminando la necessità di strumenti esterni.

# Ottieni dettagli completi sulla connessione
Get-NetTCPConnection -LocalPort 3000 | Format-List

# Filtra per ottenere solo il PID e lo stato
Get-NetTCPConnection -LocalPort 3000 | Select-Object OwningProcess, State, LocalAddress

2. Prompt dei Comandi (cmd)

Il classico netstat è ancora ampiamente utilizzato.

# -a: Tutte le connessioni
# -n: Numerico
# -o: Mostra PID proprietario
netstat -ano | findstr :3000

Per terminare il processo dal prompt dei comandi:

taskkill /PID <PID> /F

Gestione Programmatica dell’Errore

Invece di lasciare che l’applicazione crashi, puoi gestire l’errore EADDRINUSE nel tuo codice Node.js. Questo è utile per implementare logiche di riprova o fallback.

Esempio: Riprovare su una Porta Diversa

const http = require('http');
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

const startServer = (retryPort) => {
  const serverPort = retryPort || port;
  
  server.listen(serverPort, () => {
    console.log(`Server in esecuzione su http://localhost:${serverPort}/`);
  });

  server.on('error', (e) => {
    if (e.code === 'EADDRINUSE') {
      console.log(`Porta ${serverPort} occupata, riprovo con ${serverPort + 1}...`);
      server.close(); // Chiudi il server fallito
      startServer(serverPort + 1); // Riprova incrementando la porta
    } else {
      console.error('Errore del server:', e);
    }
  });
};

startServer();

Esempio: Usare una Porta Casuale

Se la porta specifica non è importante (es. durante i test), lascia che il sistema operativo ne assegni una libera passando 0.

server.listen(0, () => {
  const assignedPort = server.address().port;
  console.log(`Server avviato su porta casuale: ${assignedPort}`);
});

Prevenzione e Best Practices

  1. Graceful Shutdown: Assicurati che la tua applicazione gestisca i segnali di terminazione (SIGINT, SIGTERM) per chiudere pulitamente le connessioni e rilasciare la porta.

    process.on('SIGTERM', () => {
      server.close(() => {
        console.log('Processo terminato');
      });
    });
  2. Ambienti di Sviluppo (Nodemon): Se usi nodemon, assicurati che non lasci processi orfani. A volte, nodemon può riavviare l’app prima che il processo precedente abbia rilasciato completamente la porta.

  3. Container Docker: Assicurati di mappare correttamente le porte nel docker-compose.yml. Un errore EADDRINUSE in Docker spesso significa che stai cercando di mappare più container sulla stessa porta dell’host.

    ports:
      - "3000:3000" # Host:Container

    Se hai più servizi, usa porte host diverse (es. 3001:3000).

FAQ - Domande Frequenti

Perché succede ogni volta che salvo un file con nodemon?

Questo accade spesso se l’applicazione non gestisce correttamente il segnale di riavvio inviato da nodemon. Nodemon invia un segnale (default SIGUSR2) per riavviare. Se il tuo codice non chiude il server (server.close()) alla ricezione del segnale, il nuovo processo tenterà di avviarsi mentre il vecchio socket è ancora attivo.

Come posso prevenire questo errore nelle pipeline CI/CD?

Negli ambienti CI (come GitHub Actions o Jenkins), l’hardcoding delle porte (es. 3000) causa spesso conflitti se più job girano sulla stessa macchina. La best practice è utilizzare app.listen(0) per lasciare che il sistema operativo assegni una porta effimera libera, evitando collisioni.

È sicuro usare kill -9 per terminare il processo?

kill -9 invia il segnale SIGKILL, che termina il processo immediatamente senza permettergli di eseguire operazioni di pulizia (come chiudere connessioni al database o scrivere log). Sebbene risolva l’errore EADDRINUSE, dovrebbe essere usato come ultima risorsa. Preferisci prima kill -15 (SIGTERM).

Cosa significa listen EADDRINUSE: address already in use :::3000?

I tre due punti ::: indicano un indirizzo IPv6. Node.js, per default in molte versioni, tenta di ascoltare sia su IPv4 che su IPv6 se non viene specificato un host. Questo errore conferma che la porta 3000 è occupata sull’interfaccia IPv6 (che spesso copre anche IPv4 in modalità dual-stack).

Posso vedere quale applicazione sta usando la porta su Windows senza comandi?

Sì. Puoi aprire “Gestione Risorse” (Resource Monitor), andare alla scheda “Rete” e guardare la sezione “Porte in ascolto” (Listening Ports). Lì troverai l’elenco delle porte e i nomi dei processi associati, permettendoti di identificarli visivamente.

Errori Correlati