What is EADDRINUSE? Meaning, Causes & How to Fix It

EADDRINUSE is a system-level error that occurs when a process tries to bind to a TCP port that another process is already using.

Updated April 20265 min read

EADDRINUSE: the error explained

EADDRINUSE stands for Error: Address Already In Use. It is a POSIX error code (errno 48 on macOS, 98 on Linux) that the operating system returns when a process calls bind() on a TCP socket, but another process already holds that address+port combination.

The full error message in Node.js looks like this:

Error: listen EADDRINUSE: address already in use :::3000
    at Server.setupListenHandle [as _setupListenHandle] (net.js:1331:16)
    at listenInCluster (net.js:1379:12)
    at Server.listen (net.js:1465:7)

The :::3000 part means port 3000 on all IPv6 (and IPv4) interfaces. The triple colon is IPv6 notation for "all addresses."

How TCP port binding works

When a server application starts, it goes through these steps:

  1. socket() - Create a new TCP socket
  2. bind() - Associate the socket with a specific IP address and port number
  3. listen() - Start accepting incoming connections

The operating system enforces a rule: only one process can bind() to a given address+port at a time. If another process is already bound to 0.0.0.0:3000, any new bind() call for the same port fails with EADDRINUSE.

Common causes of EADDRINUSE

1. A previous server instance is still running

You started a dev server, closed the terminal, but the process is still alive in the background. This is the most common cause.

2. Hot reload created a duplicate

Tools like nodemon or Next.js hot reload sometimes spawn a new server process without killing the old one, leaving both bound to the same port.

3. Multiple projects on the same port

Two different projects both default to port 3000. React, Next.js, Express, and Rails all use 3000 by default.

4. TIME_WAIT state

After a TCP connection closes, the OS keeps the socket in TIME_WAIT for 30-120 seconds to handle late-arriving packets. During this window, no new process can bind to that port.

5. System service using the port

On macOS Monterey+, AirPlay Receiver uses port 5000. On some Linux distros, Avahi uses port 5353. These system services silently occupy common development ports.

How to fix EADDRINUSE

Quick fix with portrm

$ ptrm fix 3000
  Port 3000 in use
  Next.js (PID 48291) - node
  SAFE - dev server, safe to kill
  Killed PID 48291. Port 3000 is free.

Manual fix on macOS/Linux

$ lsof -i :3000
$ kill -9 <PID>

Manual fix on Windows

> netstat -ano | findstr :3000
> taskkill /PID <PID> /F

Prevent EADDRINUSE in your code

Handle the error gracefully

// Node.js: catch EADDRINUSE and suggest a fix
server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.error(`Port ${port} is in use.`);
    console.error(`Run: ptrm fix ${port}`);
    process.exit(1);
  }
});

Use SO_REUSEADDR

The SO_REUSEADDR socket option lets a new process bind to a port that is in TIME_WAIT state. Node.js enables this by default for server.listen(), but not all languages do.

Use portrm preflight

$ ptrm preflight 3000 && npm run dev

This checks if port 3000 is free before starting your server. If it is occupied, it exits with a helpful message showing the conflicting process.

Fix EADDRINUSE in one command

portrm identifies the process, checks safety, and frees the port. No PID hunting required.