localhost:5173 / port-in-use
Finding and freeing whatever is holding port 5173
Run lsof -nP -iTCP:5173 -sTCP:LISTEN on macOS or Linux, netstat -ano | findstr :5173 on Windows, to get the PID holding the port, then kill it — or leave it alone and read the port Vite printed instead, because without strictPort Vite has already moved on.
Port 5173 is in use, trying another one...Name the process first, kill it second
The PID is not the interesting part — the command name is. It tells you whether this is yesterday's dev server, a second project, or something you did not know was running. Kill first and ask later is how people take down a database container they needed.
# macOS / Linux — command, PID, user, address $ lsof -nP -iTCP:5173 -sTCP:LISTEN COMMAND PID USER FD TYPE NODE NAME node 96196 julian.weber 12u IPv4 TCP 127.0.0.1:5173 (LISTEN) # Linux without lsof $ ss -ltnp 'sport = :5173' # Windows — PID in the last column $ netstat -ano | findstr :5173 $ tasklist /FI "PID eq <pid>"
Then free it
A dev server that was never stopped is the usual owner. Closing the terminal tab does not always reach the process — on Windows it often does not, because npm sits between your shell and node.
# macOS / Linux $ lsof -ti:5173 | xargs kill -9 # Windows (PowerShell) $ Get-NetTCPConnection -LocalPort 5173 | Select-Object -ExpandProperty OwningProcess $ Stop-Process -Id <pid> -Force # either platform, nothing to look up $ npx kill-port 5173
Two messages, and only one of them is an error
Vite prints two different strings and people quote them interchangeably. They come from different branches of the same function and mean opposite things: the first is informational and the server is running somewhere else, the second is a thrown error and nothing is running at all.
# default: strictPort is off. Not an error. Read the Local: line. Port 5173 is in use, trying another one... ➜ Local: http://localhost:5174/ # strictPort: true. Thrown, the process exits. Error: Port 5173 is already in use
How far Vite counts before it gives up
The search is not a couple of attempts. Vite walks the port upwards from the configured one to 65535 and only then fails, which is why you can end up on a port nowhere near 5173 after a long-running session with several crashed servers. The final message names both ends of the range it tried.
Error: No available ports found between 5173 and 65535The port is free and still taken
Since Vite 8 the dev server does not just try to bind and react to the failure. It first checks whether 5173 is free on the wildcard addresses 0.0.0.0 and ::, and treats the port as taken if either of them is occupied — even when the host it would actually bind to is available. That is the case that looks impossible: nothing is listening on 127.0.0.1:5173, localhost:5173 would bind fine, and Vite still moves to 5174. The usual culprit is a container publishing 5173 on all interfaces.
# something holds 0.0.0.0:5173 — a container, a second machine-wide server $ docker ps --filter publish=5173 # reproduced on macOS 14.09.2026: the loopback bind succeeds anyway 127.0.0.1 bind while 0.0.0.0 held -> OK # Vite 8 still steps aside, unless you insist Port 5173 is in use on a wildcard address, but localhost:5173 is available. There may be another server running on a wildcard IP on port 5173.
Insisting on 5173 when the wildcard is busy
That warning only appears with strictPort: true. Since Vite 8.0.9 strictPort no longer refuses on the wildcard pre-check alone — it attempts the real bind, and if that succeeds you get your port plus the warning. So strictPort is not only the option that makes Vite fail loudly; it is also the one that makes it try harder.
export default defineConfig({
server: {
port: 5173,
strictPort: true, // bind 5173 or exit — no silent 5174
},
})When nothing owns the port on Windows
If netstat shows no line for 5173 and the bind still fails, the port is reserved rather than used. Hyper-V, WSL2 and Docker Desktop reserve dynamic TCP ranges at boot, and a reserved range blocks binding without any process to point at. Check the exclusions before hunting for a PID that does not exist.
> netsh interface ipv4 show excludedportrange protocol=tcp # 5173 inside one of the listed ranges = reserved, not used. # Move the dev server instead: server.port in vite.config.js.
# faq
Questions
How do I find what is using port 5173?
lsof -nP -iTCP:5173 -sTCP:LISTEN on macOS and Linux, netstat -ano | findstr :5173 on Windows. Both give you the PID; tasklist or ps turns it into a command name.
Is "Port 5173 is in use, trying another one..." an error?
No. It is an info message and the dev server is running — on the next free port, which it prints in the Local: line. The error version reads "Port 5173 is already in use" and only appears with strictPort enabled.
Which port does Vite move to?
The next free one upwards, checked one by one from the configured port to 65535. Usually 5174, but after several abandoned servers it can be considerably higher.
Why does Vite skip 5173 when nothing is listening on localhost?
Vite 8 checks the wildcard addresses 0.0.0.0 and :: before binding. Something bound to all interfaces — commonly a container publishing 5173 — marks the port as taken even though the loopback bind would have worked.
Can I stop Vite from switching ports?
Set server.strictPort: true, or pass --strictPort. Vite then exits with an error instead of moving, and since 8.0.9 it also attempts the bind even when only the wildcard address is occupied.
# next
Related
# sources
- Vite — server.port
- Vite — server.strictPort
- Vite CLI — --strictPort
- Vite source — httpServerStart (v8.3.0)
- Vite changelog — detect port conflicts on wildcard hosts (8.0.0)
Checked against the Vite documentation on 2026-09-14.