← Back to blog

Guide

Vite port 5173 already in use: why it usually moves, and what to do when it should not

September 14, 20263 min read

Vite behaves differently from most dev servers when its port is taken, and the difference is the source of a specific kind of confusion.

Vite does not fail, it moves

Start Vite while something else holds 5173 and you get a note rather than an error:

Port 5173 is in use, trying another one...
➜  Local:   http://localhost:5174/

That is deliberate and usually convenient. It is also why people end up with a browser tab on 5173 showing an old build while the dev server they just started is answering on 5174, editing files that never appear.

If you are staring at changes that will not show up, check the port in your terminal before anything else. It is the most common cause by a wide margin.

Make it fail instead, with strictPort

When the port matters, an OAuth callback, a CORS allowlist, a proxy config, a teammate’s bookmark, silently moving is worse than failing. Tell Vite to insist:

// vite.config.js
export default {
  server: {
    port: 5173,
    strictPort: true,
  },
}

With strictPort: true, Vite exits with an error instead of shopping for another port. That converts a confusing symptom into a clear one, which is almost always the better trade in a project with fixed URLs.

Finding what actually holds 5173

Now you need the culprit. Ask the port directly:

lsof -i :5173

Then terminate it:

lsof -ti :5173 | xargs kill

-t prints only process IDs, and xargs hands all of them to a single kill. A plain kill sends SIGTERM, which lets the process shut down cleanly. Only add -9 if it refuses to go.

Why it is usually your own Vite

Nine times out of ten the process holding 5173 is another Vite from the same project. The usual paths to that state:

You closed the terminal instead of stopping the server. Ctrl+C sends SIGTERM and Vite releases the port. Closing the window can leave it orphaned.

Your editor is running it. VS Code’s integrated terminal, or a run configuration, can keep a dev server alive in a panel you are not looking at. It also survives closing the folder in some setups.

Two projects, same default. Vite defaults to 5173 for every project, so a second checkout collides with the first by design.

When 5174 is also taken

If Vite keeps climbing, 5174, 5175, 5176, you probably have several orphaned servers stacked up rather than one. Look at everything in the neighbourhood at once:

lsof -i -P -n -sTCP:LISTEN | grep -E ':517[0-9]'

If that returns four node processes, they are almost certainly all yours. Clearing them is the same command applied to the range, or one port at a time.

Preventing the repeat

Give each project its own port in vite.config.js rather than relying on the default. A project on 5173, another on 5273, another on 5373, and the collisions stop being a daily event. Combine that with strictPort: true and a conflict becomes a clear error at startup instead of a silent move.

Related reading: what EADDRINUSE actually means, which explains the case where a port is held with no process to kill.

Bosun shows every listening port in your menu bar with the process behind it, so a stray dev server is visible before it costs you twenty minutes. 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.