You run npm run dev and get this instead of a server:
Error: listen EADDRINUSE: address already in use :::3000
Nothing is wrong with your project. Something else is already listening on that port, and nine times out of ten it’s you: a dev server from yesterday, still running in a terminal tab you closed, or one an AI coding agent started to check its work and never stopped.
Where ghost servers come from
- Closed terminals. Closing a tab or window doesn’t always stop what’s in it. Tools started with
&,nohup, or a process manager keep going, and their parent becomeslaunchd(macOS) orinit(Linux). That’s an orphaned process. - Coding agents. Claude Code, Cursor, Codex and friends happily start
vite,next devorpython -m http.serverto test a change. When the session ends, the server often doesn’t. - Port hopping. Vite and Astro quietly move to the next free port. So the ghost on
:5173doesn’t error; you just end up on:5174,:5175… and the old ones never die.
Each one holds a port and some memory, and many keep file watchers running. Here’s what a typical evening looks like. Press a hollow socket, or let it play:
:4322 · astro previeworphaned 7d182 MB:3000 · next devorphaned 1d312 MB:8000 · manage.py runserverup 9h64 MB:5173 · viteConnected:4321 · astro devConnected:8787 · wrangler devStarted 25m agoStep 1: find what’s listening
That gives you a PID. Before you stop it, find out what it actually is and where it runs from:
Step 2: check nobody is using it
A server you forgot isn’t automatically a server nobody needs. If a browser tab, a mobile simulator or another service is connected right now, there’s an established connection on that port:
Empty output, a process that has been up for hours, and a parent PID of 1: that’s a ghost.
Step 3: stop it politely
What about killall node or pkill -f node? Please don’t. Your editor’s language servers, MCP servers, the agent you’re using and half your desktop apps may be Node processes too.
Or let Gigaflush find them
Gigaflush’s Servers tab does the checks above for every port at once, every time you open it, and only suggests a server when all of these are true:
- It’s your process, and a dev runtime: Node, Bun, Deno, Python, Ruby or PHP. Databases, Docker, editors, agents and language servers are never listed.
- Nothing is connected to its ports.
- It has run for at least 30 minutes at under 2% CPU on average.
- It’s orphaned, or it has been running for 6 hours or more.
The patch panel shows every dev server you have running, so you can see what was left alone and why. Stopping one checks it again by PID and start time, then sends SIGTERM. Child processes such as bundlers and workerd get the same request. The whole check takes about 0.2 seconds and nothing runs in the background. It’s available on macOS and Linux; Windows is next.
Keep it from happening again
- Pin the port so a ghost fails loudly instead of pushing you to the next port:
vite --strictPort, orserver.strictPort: truein your Vite config. - Tell your agent to clean up. Add a line to your
CLAUDE.mdorAGENTS.mdfile, or your Cursor rules: “Stop any dev server you start before finishing.” - Prefer foreground servers in a terminal you can see, over
&andnohup.