← Back to blog

Guide

React: Something is already running on port 3000. Would you like to run on another port?

September 14, 20263 min read

Create React App handles this differently from every other dev server. It does not fail, and it does not silently move. It asks:

? Something is already running on port 3000.
Would you like to run the app on another port instead? (Y/n)

The default is yes, so pressing Enter accepts. That is usually the wrong answer, and it is worth knowing why before it becomes a habit.

Why saying yes hides the problem

Accept, and your app opens on 3001 while the thing on 3000 keeps running. You have not solved anything, you have stepped around it. Do that a few times across a few days and you accumulate orphaned dev servers on 3000, 3001, 3002, each holding memory and each invisible.

Worse, anything configured for localhost:3000 now points at the wrong app. An OAuth callback, a proxy in package.json, a mocked API. The failure shows up later as a login that does not work, and you will not connect it to a prompt you dismissed on Tuesday.

Answer n and find out what is actually on 3000. It takes ten seconds.

Finding it

lsof -i :3000

If it is a node process, it is almost certainly your own previous run:

lsof -ti :3000 | xargs kill

-t prints just the process IDs, xargs passes all of them to a single kill, and a plain kill sends SIGTERM so the process can exit cleanly. Use -9 only if it ignores that.

Setting the port properly

If you genuinely want a different port, set it rather than answering a prompt each time.

PORT=3001 npm start

Or permanently, in a .env file at the project root:

PORT=3001

CRA reads PORT from the environment, so this survives restarts and applies to everyone on the project. Much better than a prompt nobody reads.

A note on Create React App

If you are starting something new in 2026, CRA is no longer the default recommendation and has not been for a while. Most new React projects use Vite or Next.js, both of which are faster and actively maintained.

That matters here because the behaviour differs. Vite quietly moves to the next port and Next.js does the same, neither of them asks. If you migrate, the prompt disappears and the silent move takes its place, which has its own trap.

When the port is held by something that is not Node

Two cases come up regularly.

Docker. A container publishing 3000 shows up as docker-proxy. Killing it does nothing useful, Docker republishes immediately:

docker ps --filter "publish=3000"
docker stop <container>

A different framework. Rails, Next.js and plenty of others also default to 3000. If you have two projects open, they are competing for it by design. Give each one a fixed, different port and the collisions stop.

When nothing is listening but the prompt still appears

If lsof -i :3000 prints nothing and you still get asked, the port is in TIME_WAIT, a TCP state that reserves a recently closed port for around thirty seconds. There is no process to kill, so waiting is the fix.

Details in what EADDRINUSE actually means.

Bosun lists what is on each port from the menu bar, so answering that prompt becomes a decision rather than a guess. macOS 14 or later, 14 day trial.

See this instead of typing it

Bosun lives in your menu bar and shows every open port on your Mac, live, mapped to the process behind it. One-click kill, SIGTERM first. Useful the first time this happens. Genuinely useful the fifth time it happens in one afternoon.