Skip to content

Fix: Port 3000 Is Already in Use (EADDRINUSE)

FixDevs · (Updated: )

Part of:  React & Frontend Errors

Quick Answer

How to fix 'port 3000 is already in use', 'EADDRINUSE', and 'address already in use :::3000' errors in Node.js, React, Next.js, and other frameworks on macOS, Linux, and Windows.

The Error

You start your development server and get one of these errors:

Node.js / Express:

Error: listen EADDRINUSE: address already in use :::3000

React (create-react-app):

Something is already running on port 3000.

Next.js:

Port 3000 is already in use.
Use `next dev --port` to specify a different port.

All of these mean the same thing: something else on your machine is already listening on port 3000.

Why This Happens

Port 3000 can only be used by one process at a time. The kernel enforces this — a bind() call on a port that is already in use returns EADDRINUSE, and Node.js surfaces that as the runtime error you see. There is no way for two processes to share the same TCP port on the same network interface unless they explicitly use SO_REUSEPORT, which dev servers do not.

The port is not a Node-specific thing either. Any process — a Python Flask server, a Java app, a Docker container with a port mapping, or even a system service — can hold port 3000 and block your dev server. That is why the troubleshooting steps below focus on identifying which process holds the port, not on something specific to your framework.

Common causes:

  • A previous dev server is still running. You closed the terminal tab but the process didn’t stop.
  • Another project is using the same port. You have two apps both defaulting to port 3000.
  • A zombie Node.js process. The process crashed but didn’t release the port.
  • A Docker container is mapping a container port to 3000 on your host machine.
  • A system or background service (like a database admin panel) is bound to that port.
  • macOS AirPlay Receiver has grabbed port 5000 or 7000 (relevant if you switched to those as a workaround — see history below).

A Note on Dev Server Port Conventions

The choice of 3000, 5000, 8000, and 8080 as dev defaults is older than most current frameworks. The convention dates back to the early Express era — Express’s generator scaffolds chose 3000, Rails chose 3000, and a generation of tutorials standardized on it. That choice eventually became a problem because dozens of dev tools defaulted to the same handful of ports.

macOS Monterey (2021) caused the most painful collision. Apple started binding the AirPlay Receiver service to port 5000 by default, which silently broke Flask and dozens of other Python dev servers that had used 5000 for years. macOS Ventura extended the same pattern to port 7000 in some configurations. The fix is either to disable AirPlay Receiver under System Settings > General > AirDrop & Handoff > AirPlay Receiver, or to switch your dev server to a different port. This is why current Flask documentation recommends 5001 over 5000.

Windows reserves port ranges that you cannot bind to even though nothing is actively listening. Hyper-V, WSL2, and Windows Containers reserve large ranges of dynamic ports for internal use. Run netsh interface ipv4 show excludedportrange protocol=tcp to see them. If your “free” port appears in that list, no process holds it but you still cannot bind. The workaround is to pick a port outside the reserved ranges or to use netsh int ipv4 add excludedportrange ... to carve out a specific exclusion. This is far more common on Windows 11 with WSL2 enabled.

Next.js auto-increments now. Since Next 14, next dev automatically tries the next free port (3001, 3002, …) when 3000 is taken instead of failing. The error message above still appears on older Next versions and on most other tools that have not adopted that behavior.

Fix 1: Find and Kill the Process (macOS / Linux)

Find which process is using port 3000:

lsof -i :3000

You’ll see output like:

COMMAND   PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
node    12345   you   23u  IPv6  0x1234      0t0  TCP *:3000 (LISTEN)

Kill the process using its PID. First try a graceful shutdown:

kill 12345

If the process doesn’t stop after a few seconds, force-kill it:

kill -9 12345

One-liner — find and kill in a single command:

lsof -ti :3000 | xargs kill

The -t flag makes lsof output only the PID, which is piped directly to kill. Use xargs kill -9 instead if the graceful kill doesn’t work.

Fix 2: Find and Kill the Process (Windows)

Find which process is using port 3000:

netstat -ano | findstr :3000

You’ll see output like:

  TCP    0.0.0.0:3000    0.0.0.0:0    LISTENING    12345

The last number (12345) is the PID. Kill it:

taskkill /PID 12345 /F

One-liner using PowerShell:

Stop-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess -Force

Why this matters: Only one process can bind to a specific port at a time. If a previous dev server is still running in the background after you closed the terminal tab, it silently holds the port. This is especially common with Node.js processes that don’t exit cleanly after a crash.

Fix 3: Use npx kill-port (Cross-Platform)

The simplest solution that works on macOS, Linux, and Windows:

npx kill-port 3000

You can kill multiple ports at once:

npx kill-port 3000 3001 8080

No global install required — npx downloads and runs it on the fly.

Fix 4: Change the Default Port

If you’d rather keep whatever is on port 3000 running, change your app’s port instead.

React (create-react-app):

PORT=3001 react-scripts start

On Windows (cmd):

set PORT=3001 && react-scripts start

Or use cross-env for a cross-platform solution in package.json:

{
  "scripts": {
    "start": "cross-env PORT=3001 react-scripts start"
  }
}

Next.js:

npx next dev --port 3001

Or in package.json:

{
  "scripts": {
    "dev": "next dev --port 3001"
  }
}

Express:

Change the port in your code:

const port = process.env.PORT || 3001;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

Then either edit the fallback value or set the environment variable:

PORT=3001 node server.js

If process.env.PORT ends up undefined inside your app, see Fix: process.env.VARIABLE_NAME is undefined.

Vite:

npx vite --port 3001

Or in vite.config.js:

export default defineConfig({
  server: {
    port: 3001,
  },
});

Still Not Working?

Multiple Node Processes Are Running

Sometimes several zombie Node processes pile up. Kill them all at once:

macOS / Linux:

killall node

Windows (cmd):

taskkill /IM node.exe /F

Warning: This kills every Node.js process on your machine, including unrelated ones.

A Docker Container Is Using the Port

Check if a Docker container has port 3000 mapped:

docker ps --format "table {{.Names}}\t{{.Ports}}" | grep 3000

If you find one, stop it:

docker stop <container_name>

Or remove the port mapping by changing -p 3000:3000 to a different host port (e.g. -p 3001:3000) when you run the container.

A System Process Is Using the Port

If lsof or netstat shows a system process (not Node) on port 3000, don’t kill it blindly. Check what it is first:

macOS / Linux:

lsof -i :3000

Look at the COMMAND column. If it’s something like Grafana, a database admin panel, or another known service, either disable that service or change your app’s port instead (see Fix 4).

On macOS, AirPlay Receiver is known to occupy port 5000 (Monterey and later) and sometimes 7000, not 3000 — but it’s worth checking if any macOS system service is using your port. You can disable AirPlay Receiver under System Settings > General > AirDrop & Handoff > AirPlay Receiver if it conflicts with other projects.

Pro Tip: Instead of hunting down processes every time, consider changing your app’s default port. For Next.js, add --port 3001 to your dev script. For Express, read from process.env.PORT with a fallback. This avoids collisions when you run multiple projects simultaneously.

The Port Is Freed but the Error Persists

After killing the process, if you still get the error, wait a few seconds. The OS may keep the port in a TIME_WAIT state briefly. If it persists:

macOS / Linux — check if anything is still holding it:

lsof -i :3000

If the output is empty and the error continues, restart your terminal or IDE. Some tools cache the port assignment.

Windows Port Is in an Excluded Range

If netstat shows nothing listening on 3000 but Node still refuses to bind, the port may sit inside a Windows-reserved range. List the reserved ranges:

netsh interface ipv4 show excludedportrange protocol=tcp

If port 3000 (or whatever port you are trying to use) appears inside one of the listed ranges, the kernel is blocking the bind even though the port is idle. WSL2 and Hyper-V are the most common culprits, because Windows reserves a wide dynamic range at boot. Either pick a port outside the listed ranges, or restart Windows to redo the reservation (the ranges are chosen dynamically and may move on restart). For a permanent carve-out:

# Run as Administrator
netsh int ipv4 add excludedportrange protocol=tcp startport=3000 numberofports=1

IPv6 vs IPv4 Conflict

The error address already in use :::3000 (note the three colons) is IPv6 syntax. Some platforms — notably older Node releases on Windows — bind to IPv6 by default and refuse to start if IPv4 already holds the port (or vice versa). Force IPv4 by binding to 0.0.0.0 instead of leaving the host unset:

app.listen(3000, '0.0.0.0');

This usually resolves the conflict on machines where Docker Desktop or another service holds the IPv4 side.

Dev Server Started Twice by a File Watcher

If you use nodemon, ts-node-dev, or next dev and the port frees and re-binds in a tight loop, your file watcher is restarting too quickly. The previous instance has not released the socket yet when the new one tries to bind. Add a small delay (--delay 1 for nodemon) or restart your IDE — VS Code’s auto-save sometimes triggers two restarts back-to-back. If your dev server is crashing on startup with EADDRINUSE and then a deeper Node error, see Fix: Node.js uncaught exception. If Next.js dev mode is failing in a different way after switching ports, see Fix: Next.js 500 internal server error.


Related: If you’re seeing npm dependency errors when setting up your project, see Fix: npm ERR! ERESOLVE unable to resolve dependency tree.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles