Your app refuses to start:
Error: listen EADDRINUSE: address already in use :::3000
Something already owns that port. Usually it is a previous run of your own app that did not exit cleanly. The fix is two steps — find out what is holding it, then decide whether to stop that process or move your app — and both take seconds once you know the right command.
Key Takeaways
- The error means another process is already bound to the port your application wants.
- Identify the owning process before killing anything; the port may belong to a service you need.
- On Linux use ss -ltnp, on macOS use lsof -i, to map a port to a PID.
- Send SIGTERM first and reserve kill -9 for processes that ignore it, since SIGKILL skips cleanup.
- A port stuck in TIME_WAIT is normal and clears on its own; SO_REUSEADDR in your app avoids the wait.
Quick Fix
Identify which process is holding the port before taking any action. One command maps the port to a PID and command name, which tells you whether to stop it or move your app to a different port.
sudo ss -ltnp | grep :3000
Step 1: Find What Owns the Port
On modern Linux, ss is the tool:
sudo ss -ltnp | grep :3000
The output ends with the owning process, for example users:(("node",pid=48213,fd=23)). The sudo matters — without it the process name is hidden for anything you do not own.
On macOS, or on Linux without ss:
sudo lsof -i :3000
Both give you a PID and a command name. Before you act, confirm what that process actually is:
ps -fp 48213
This one check prevents the classic mistake of killing a database or a reverse proxy because it happened to hold the port you wanted.
Step 2: Stop It Gracefully
If it is a stale copy of your own app, ask it to exit:
kill 48213
Plain kill sends SIGTERM, which lets the process close files, finish requests, and shut down cleanly. Wait a second and confirm the port is free:
sudo ss -ltnp | grep :3000
Empty output means the port is available. Only if the process ignores SIGTERM should you escalate:
kill -9 48213
SIGKILL cannot be caught, so the process gets no chance to flush buffers or release locks. For a dev server that is harmless; for a database or a queue worker mid-job it can leave corrupted state. Try SIGTERM first, every time.
Step 3: When It Is a Managed Service
If the owner turns out to be something systemd manages — nginx, Apache, PostgreSQL, Redis — do not kill the PID. systemd will restart it and you will be confused about why the port is occupied again. Stop it properly:
sudo systemctl stop nginx
And if two services genuinely both want the port, the real fix is to move one. Changing your app’s port is almost always easier than relocating a system service:
PORT=3001 npm start
The TIME_WAIT Case
Sometimes you stop the process, nothing shows as listening, and the bind still fails. Check for sockets in a closing state:
ss -tan | grep :3000
If you see TIME_WAIT, the kernel is holding the socket for up to a couple of minutes to catch stray packets from the old connection. This is correct TCP behaviour, not a fault.
Two sane responses. Wait — it clears on its own. Or fix it properly in your application by setting SO_REUSEADDR on the listening socket, which lets a new process bind while old connections drain. Most frameworks expose this; in Node it is the default, in Python’s socketserver you set allow_reuse_address = True.
Resist the urge to lower the kernel’s TIME_WAIT timeout globally. It is a system-wide change made to avoid a two-minute wait during development, and it weakens a protection that exists for good reason.
Docker Adds One More Place to Look
If nothing on the host holds the port, a container may have published it:
docker ps --format "table {{.Names}}\t{{.Ports}}"
Stop the offending container by name:
docker stop my-container
Containers from a previous docker compose up that was interrupted are a frequent cause, and they do not appear in a casual ps listing on the host.
Verify the Fix
Confirm nothing is listening before you restart:
sudo ss -ltnp | grep :3000 || echo "port 3000 is free"
Then start your app and confirm it took the port, rather than trusting that no error appeared:
sudo ss -ltnp | grep :3000
You should now see your own process as the owner.
Prevent It From Recurring
Most repeat cases come from development servers detached from a terminal. Stop them with Ctrl+C rather than closing the window, so they receive SIGTERM and release the port.
Keep a one-liner handy for the times it happens anyway:
kill $(sudo lsof -t -i:3000)
Note this kills every process on that port, so run the identification step first if there is any doubt. For services you run regularly, letting systemd manage them removes the problem entirely — it tracks the process and shuts it down cleanly before starting a replacement.
Frequently Asked Questions
Why does the port stay busy after I killed the process?
The socket is likely in TIME_WAIT, a normal TCP state lasting up to two minutes. Confirm with ss -tan | grep PORT. It clears on its own, or you can set SO_REUSEADDR in your application to bind immediately.
What is the difference between kill and kill -9?
kill sends SIGTERM, which asks the process to shut down cleanly. kill -9 sends SIGKILL, which the process cannot catch or handle. Use SIGTERM first so the process can release resources properly.
Why does lsof show nothing but the port is still in use?
Run it with sudo — without elevated privileges you only see your own processes. On Linux, sudo ss -ltnp is more reliable. Also check Docker, since published container ports do not appear as host processes.
Can two programs share the same port?
Not on the same address and protocol, except with SO_REUSEPORT where processes explicitly opt in for load balancing. Normally one listener owns a port, which is why the second attempt fails.