Node.js Port Conflict Fix: EADDRINUSE & Beyond

Every Node.js port conflict scenario and how to fix it. Covers Express, Next.js, Vite, NestJS, and Fastify.

Updated April 20265 min read

The error you are seeing

When a Node.js application tries to start and the port is already taken, you get one of these errors:

Error: listen EADDRINUSE: address already in use :::3000
// or
Error: listen EADDRINUSE: address already in use 0.0.0.0:8080

This means another process is already bound to that port. The fix is to either kill the existing process or use a different port.

Quick fix: portrm

$ ptrm fix 3000
  Port 3000 in use
  Express.js (PID 29104) - node
  SAFE - dev server
  Killed PID 29104. Port 3000 is free.

Framework-specific fixes

Express.js

// Graceful error handling for Express
const port = process.env.PORT || 3000;

app.listen(port)
  .on('error', (err) => {
    if (err.code === 'EADDRINUSE') {
      console.error(`Port ${port} is busy. Try: ptrm fix ${port}`);
      process.exit(1);
    }
  })
  .on('listening', () => {
    console.log(`Server running on port ${port}`);
  });

Next.js

# Use a different port
$ npx next dev --port 3001

# Or free the default port first
$ ptrm fix 3000 -y && npx next dev

# Set port via environment variable
$ PORT=3001 npx next dev

Vite (React, Vue, Svelte)

# Vite auto-increments by default, but if disabled:
$ npx vite --port 5174

# Re-enable auto port increment in vite.config.js
export default defineConfig({
  server: {
    strictPort: false  // tries next port if busy
  }
});

NestJS

// main.ts - handle port conflicts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const port = process.env.PORT || 3000;
  try {
    await app.listen(port);
  } catch (err) {
    if (err.code === 'EADDRINUSE') {
      console.error(`Port ${port} is busy. Run: ptrm fix ${port}`);
      process.exit(1);
    }
    throw err;
  }
}

Fastify

fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    if (err.code === 'EADDRINUSE') {
      console.error('Port 3000 is busy. Run: ptrm fix 3000');
    }
    process.exit(1);
  }
});

Find what is using the port

# portrm (cross-platform, shows service name)
$ ptrm 3000

# macOS/Linux
$ lsof -i :3000

# Windows
> netstat -ano | findstr :3000

Programmatic port finding

Find a free port automatically in your Node.js code:

// Use port 0 to let the OS pick a free port
const server = app.listen(0, () => {
  const port = server.address().port;
  console.log(`Server on port ${port}`);
});

Prevention with .ptrm.toml

Map each service to a dedicated port so conflicts never happen:

# .ptrm.toml
[[services]]
name = "frontend"
port = 3000
command = "npm run dev"

[[services]]
name = "api"
port = 8080
command = "node server.js"
$ ptrm preflight   # check all ports before starting
$ ptrm up          # start all services, auto-resolve conflicts

Fix Node.js port conflicts instantly

portrm detects Express, Next.js, Vite, and 40+ services. One command to identify and fix.