EADDRINUSE: address already in use — como liberar o porto
Resposta rápida
Outro proceso xa está a escoitar no porto. Atópao e mátao:
- macOS / Linux:
lsof -i :3000→kill -9 <PID> - Windows:
netstat -ano | findstr :3000→taskkill /PID <pid> /F - Calquera SO, un só comando:
npx kill-port 3000
…ou simplemente arrinca o teu servidor noutro porto. O erro completo ten esta pinta:
MAKINOTE$ yarn startyarn run v1.22.19$ next startError: listen EADDRINUSE: address already in use 0.0.0.0:3000 at Server.setupListenHandle [as _listen2] (node:net:1432:16) at listenInCluster (node:net:1480:12) at doListen (node:net:1629:7) at processTicksAndRejections (node:internal/process/task_queues:84:21) { code: 'EADDRINUSE', errno: -48, syscall: 'listen', address: '0.0.0.0', port: 3000}
Por que ocorre
EADDRINUSE significa que a dirección e o porto que quere o teu servidor xa están ocupados. Nunha máquina de desenvolvemento a causa habitual é un servidor de desenvolvemento anterior que non se pechou ben — un proceso que crasheou, un traballo en segundo plano solto, ou unha segunda terminal que o segue executando. Menos a miúdo, outra aplicación ocupa o porto de verdade: outro servizo, un contedor de Docker ou un daemon do sistema.
O mesmo erro en calquera outra ferramenta
EADDRINUSE non é cousa de Node.js. É o sistema operativo rexeitando a chamada a bind(), e cada runtime conta ese mesmo rexeitamento á súa maneira. Se buscaches a cadea exacta que imprimiu a túa ferramenta e acabaches aquí, esta é a táboa de tradución:
| Ferramenta | O que imprime |
|---|---|
| Node.js | Error: listen EADDRINUSE: address already in use 0.0.0.0:3000 |
| Python | OSError: [Errno 48] Address already in use (48 en macOS, 98 en Linux) |
| netcat | nc: Address already in use, código de saída 1 |
| Docker | bind: address already in use |
| Go | listen tcp :8080: bind: address already in use |
| Playwright | http://localhost:3000 is already used, make sure that nothing is running on the port/url |
Os números da mensaxe de Python son a constante errno crúa, e cambian segundo a plataforma — 48 en macOS e os BSD, 98 en Linux. Iso despista cando un contedor reproduce o mesmo fallo cun número distinto ao do portátil. Reproducido en macOS 26.5:
Imprimíseo quen o imprimise, o diagnóstico non cambia: algo ocupa xa ese porto. Os comandos de abaixo serven igual con calquera ferramenta.
Que porto é, e quen adoita ocupalo
A metade destes casos non son un servidor de desenvolvemento zombi: son dous programas distintos que usan o mesmo porto por defecto. Os que convén saber:
| Porto | Dono habitual |
|---|---|
| 3000 | Next.js, Create React App, Rails, Grafana |
| 3001 | O segundo servidor que arrincaches despois de que o 3000 estivese collido |
| 5000 / 7000 | En macOS, ControlCenter cando o receptor de AirPlay está activado |
| 5173 | Vite |
| 8080 | Tomcat, Jenkins e aproximadamente todo o que se chame "HTTP alternativo" |
| 9323 | O servidor do informe HTML de Playwright |
| 5432 / 6379 | PostgreSQL / Redis — normalmente un contedor pelexando cunha instalación local |
O caso do 5000 en macOS é o que máis tempo fai perder, porque non o ocupa nada que arrincases ti. O receptor de AirPlay queda co 5000 e o 7000, así que unha app de Flask no seu porto por defecto falla nunha máquina onde o desenvolvedor non instalou nada. lsof delátao ao instante: o dono é ControlCenter, non node nin python. Desactívao en Axustes do Sistema → Xeral → AirDrop e Handoff, ou move a túa app.
O 9323 é o de Playwright, e pórtase mellor do que a xente espera — convén sabelo antes de poñerse a cazar un PID. O reporter HTML serve alí o informe por defecto, pero trata o 9323 como porto preferido, non obrigatorio. Lendo playwright-core/lib/server/utils/httpServer.js en Playwright 1.57:
Captura o EADDRINUSE e reintenta sen porto, deixando que o sistema escolla un libre. Así que un informe aberto nunha lapela non rompe a seguinte execución: só fai que o informe saia nun porto distinto do esperado.
O que si tumba unha execución de Playwright é o bloque webServer da configuración, e é outra mensaxe con outro arranxo:
O erro dache o arranxo: se o que ocupa o porto é o teu propio servidor de desenvolvemento, que é o normal, reuseExistingServer: true fai que Playwright o reutilice en vez de tentar levantar un segundo.
A dirección importa tanto como o porto
EADDRINUSE vai dunha dirección e un porto, non dun porto solto — por iso a mensaxe nomea unha, como 0.0.0.0:3000 ou ::1:9323.
Esa distinción é real: 127.0.0.1:3000 (loopback IPv4) e [::1]:3000 (loopback IPv6) son direccións distintas. Un servidor atado a unha non choca necesariamente con outro atado á outra, e un atado a 0.0.0.0 choca cos dous porque reclama todas as interfaces IPv4 da máquina. Iso explica dúas situacións confusas:
lsof -i :3000non amosa nada e aínda así o teu servidor falla — mira a dirección exacta do erro e comproba a outra familia de protocolo.- Dous servidores conviven tan ricamente "no mesmo porto", ata que un terceiro se ata a
0.0.0.0e rebenta todo.
Usa lsof -nP -iTCP:3000 -sTCP:LISTEN para ver a dirección ademais do PID: -n e -P sáltanse as resolucións de DNS e de nome de servizo, así que obtés *:3000 en vez do TCP *:hbci da saída de arriba — hbci é só /etc/services renomeándoche o porto 3000.
Liberar o porto en macOS e Linux
Atopa o proceso que ocupa o porto con lsof (en Linux tamén serven ss -ltnp ou fuser 3000/tcp):
MAKINOTE$ lsof -i :3000COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEnode 38091 xabier.lameirocardam 24u IPv6 0xee02297dd086ebc1 0t0 TCP *:hbci (LISTEN)
Despois termínao. Proba primeiro un kill <PID> limpo, e recorre a kill -9 <PID> só se o proceso o ignora:
MAKINOTE$ kill -9 38091
Liberar o porto en Windows
Lista o PID asociado ao porto e despois mátao:
netstat -ano | findstr :3000taskkill /PID 38091 /F
Un só comando en calquera SO
Se prefires non buscar PIDs, kill-port faino por ti — sen instalar nada:
npx kill-port 3000
Ou usa outro porto
Moitas veces o máis rápido é non pelexar polo porto:
PORT=3001 npm run dev # apps que len process.env.PORTnext dev -p 3001 # Next.js
Dentro de Docker
Se o servidor corre nun contedor, o porto do host ocúpao o mapeo de portos, non un PID local — lsof apuntará a com.docker. Para o contedor (docker ps e logo docker stop <id>) ou cambia o mapeo (-p 3001:3000).
Docker dío de forma o bastante distinta como para que a xente non o relacione con EADDRINUSE:
port is already allocated é a contabilidade interna de Docker — o daemon sabe que xa publicou ese porto —, mentres que bind: address already in use é o kernel rexeitando, igual que en todo o demais. O primeiro pode sobrevivir a un contedor que xa rematou: docker ps -a e borrar o contedor morto arránxao, e docker compose down é a versión bruta.
Cando nada disto funciona
Dous casos nos que o porto non é teu para collelo:
- Os portos por debaixo de 1024 precisan privilexios. Atarse ao 80 ou ao 443 como usuario normal falla con
EACCES, non conEADDRINUSE. Outro erro, outro arranxo: se lesEACCES, deixa de buscar un proceso ao que matar. - O porto está en
TIME_WAIT. Despois de pechar un socket, o sistema retén o par ata un par de minutos.lsof -i :3000amosa unha conexión pero ningún listener, e non hai nada que matar. Os servidores evítano conSO_REUSEADDR, que a maioría de frameworks xa poñen por ti; agardar tamén funciona.
