Port Monitor

Fix EADDRINUSE: address already in use

EADDRINUSE means another process is already listening on the port your server wants. Nine times out of ten it is a dev server you started earlier and forgot, or one that a tool started for you. Find it and stop it, or start yours on another port.

Updated . Applies to macOS.

What the error means

When a server starts it asks the operating system to bind a port. If any other process already owns that port, the kernel refuses with EADDRINUSE. Node prints it like this:

Error: listen EADDRINUSE: address already in use :::3000
    at Server.setupListenHandle [as _listen2] (node:net:1908:16)
    at listenInCluster (node:net:1965:12)

Other stacks report the same condition in their own words:

  • Python: OSError: [Errno 48] Address already in use on macOS (errno 98 on Linux)
  • Rails / Puma: Address already in use - bind(2) for "127.0.0.1" port 3000 (Errno::EADDRINUSE)
  • Go: listen tcp :8080: bind: address already in use

The :::3000 in Node's message is the IPv6 wildcard address, not a typo. The port is what matters.

Why the port is taken

Most likely first:

  1. The same project is already running in another terminal tab, an editor terminal, or a window you closed without stopping the server.
  2. A coding agent started it. Claude Code, Cursor, Codex and similar tools launch dev servers and preview builds to check their work and do not always stop them.
  3. A crashed parent left a child alive. npm run dev died, but the node process it spawned kept the port.
  4. Another project uses the same default port. Every Next.js app wants 3000, every Vite app 5173.
  5. A Docker container publishes the port. lsof shows the owner as com.docker.backend.
  6. On ports 5000 and 7000, it is macOS itself. AirPlay Receiver listens there. See port 5000 and 7000 on Mac.

Fix 1: find the process and stop it

Show who owns the port, then send it SIGTERM:

lsof -nP -iTCP:3000 -sTCP:LISTEN
kill <PID>

Or in one line:

kill $(lsof -ti tcp:3000 -sTCP:LISTEN)

If it is still there a second later, kill -9 it. The details, a reusable shell function and what to do when the process keeps coming back are in how to kill the process on a port on Mac.

Fix 2: start yours on another port

When the other server is doing something useful, leave it alone and move. Most tools take a flag or read PORT:

ToolCommandNote
Next.jsnext dev -p 3001Also picks the next free port by itself and prints a warning.
Vitevite --port 5174Picks the next free port unless strictPort is set.
Node servers, Create React AppPORT=3001 npm startAnything that reads process.env.PORT.
Railsbin/rails server -p 3001
Djangopython manage.py runserver 8001
Flaskflask run -p 5001Port 5000 is usually AirPlay, see below.
FastAPI / Uvicornuvicorn main:app --port 8001
Python http.serverpython3 -m http.server 8001

Two projects that must run at once deserve fixed, different ports in their .env or scripts so this stops being a daily event.

Fix 3: stop leaving servers behind

  • Stop servers with Ctrl+C in their tab instead of closing the tab or window. Closing often leaves the child process running.
  • Avoid backgrounding a dev server with & unless you also note its PID. Backgrounded servers outlive the shell.
  • After a coding agent session, list the listeners: lsof -nP -iTCP -sTCP:LISTEN. Anything you did not start yourself can go.
  • Keep a counter in the menu bar. Port Monitor shows how many dev ports are busy right now, so a leftover server is visible before you hit the error.

EADDRINUSE right after a clean stop

Rarely, the port stays reserved for a short while after the old server exits, while the kernel finishes closing connections. Node's listen sockets are set up to reuse such addresses, so this is uncommon with Node; if it happens with another runtime, wait half a minute and start again, or confirm with lsof that nothing is actually listening.