Free a Port a Dead Dev Server Still Holds
EADDRINUSE when nothing is running — how to find the real owner of a port and kill it, without guessing at PIDs.
Loading…
EADDRINUSE when nothing is running — how to find the real owner of a port and kill it, without guessing at PIDs.
Loading…
You start the dev server and get:
Error: listen EADDRINUSE: address already in use :::3000
…except nothing is running. A previous run crashed, or its parent shell died,
and the child process kept the socket. It may not even answer requests any
more — a wedged next-server can hold port 3000 while curl gets nothing
back.
lsof -nP -iTCP:3000 -sTCP:LISTEN
-nP skips DNS and port-name lookups, so it returns instantly-sTCP:LISTEN filters out clients that merely connected to the portLook at the command before you kill anything — the PID that holds the socket is often a child, and killing only the child leaves the parent to respawn it:
ps -p "$(lsof -nP -iTCP:3000 -sTCP:LISTEN -t)" -o pid=,ppid=,command=
kill $(lsof -nP -iTCP:3000 -sTCP:LISTEN -t)
Plain kill sends SIGTERM, which lets the server close its sockets and
flush its build cache. Reach for kill -9 only if it is still there a few
seconds later — SIGKILL skips cleanup, and for a bundler that can mean a
corrupt cache directory on next start.
freeport() { lsof -nP -iTCP:"$1" -sTCP:LISTEN -t | xargs -r kill; }
Then freeport 3000. The -r matters: without it, xargs runs kill with
no arguments when the port is already free, and you get a confusing usage
error instead of silence.
If the other process is something you actually want running, don't fight it:
npm run dev -- -p 3100
Most dev servers take a port flag after --. Two servers, two ports, no
detective work.
A terminal that closes without sending SIGHUP to its process group, a
crashed parent, a debugger detaching — any of these can orphan the listener.
On macOS the socket also lingers briefly in TIME_WAIT after a clean exit;
that one clears itself in seconds and is not worth killing anything over.