Port already in use? How to find and kill the process on any port (Windows, macOS, Linux)
EADDRINUSE: address already in use is the most common dev-server error there is. Here's how to find and kill the offending process on every OS — and how to stop doing it by hand.
You run your dev server and get EADDRINUSE: address already in use :::3000. Something is squatting on your port — usually a zombie process from a dev server that didn't shut down cleanly, a container you forgot about, or another project you had open last week. Here's the fastest way to find and kill it on every operating system.
macOS and Linux: lsof + kill
# Find the process listening on port 3000
lsof -i :3000
# Output shows the PID - kill it
kill -9 <PID>
# Or as a one-liner
kill -9 $(lsof -ti :3000)The -t flag makes lsof print only the PID, which is what makes the one-liner work. Prefer plain kill (SIGTERM) first if you want the process to shut down gracefully; -9 (SIGKILL) is the hammer for processes that ignore polite requests. On Linux servers without lsof, `fuser -k 3000/tcp` or `ss -lptn 'sport = :3000'` do the same job.
Windows: netstat + taskkill
# Find the PID listening on port 3000
netstat -ano | findstr :3000
# Kill it (the PID is the last column)
taskkill /PID <PID> /F
# PowerShell one-liner
Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess | Stop-Process -ForceWatch the state column in netstat output: you want the row that says LISTENING, not TIME_WAIT. TIME_WAIT entries are already-closed connections the OS is draining — they clear on their own and killing their former owner won't help.
Why this keeps happening
- Dev servers killed with the terminal's X button instead of Ctrl+C don't always release their socket - the process outlives the window.
- nodemon/watch-mode restarts can orphan the child process while the parent respawns, leaving two processes contending for the port.
- Docker containers with published ports hold the host port until the container stops - `docker ps` is worth a look before you start killing PIDs.
- VS Code's integrated terminals keep background tasks alive after the editor window closes, especially on Windows.
Stop doing this by hand
If you do this more than once a week, script it or use a tool built for it. This exact annoyance is why we built PortSlayer — run pk with no arguments and you get a full-screen dashboard of every listening port, searchable, with kill-with-confirmation on a single keystroke. It's free and MIT-licensed, works on Windows and Linux, and also speaks JSON for scripts. But even a shell alias for the one-liner above will save you the ritual of googling this page again next month.
# ~/.bashrc or ~/.zshrc
killport() {
kill -9 $(lsof -ti :"$1") && echo "Killed process on port $1"
}
# Usage
killport 3000One prevention tip
Most dev servers accept a fallback port or pick a free one automatically (Vite does this out of the box). If yours doesn't, wire your start script to check the port first and fail with a useful message instead of a stack trace. Your future self at 9am Monday will thank you.
Written by Appesto Engineering.