Describe the bug
When server.host is set to a specific IP address, Vite still rejects the configured port if that port is already in use on a different local interface.
In my case, I set server.host = '127.0.20.4', server.port = 80, and server.strictPort = true. The address 127.0.20.4:80 is actually free, and I can bind to it successfully with a plain Bun server. However, Vite exits with:
Error: Port 80 is already in use
Minimal config
vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
server: {
host: '127.0.20.4',
port: 80,
strictPort: true,
},
})
Reproduction context
I also have other local services listening on port 80, but on different loopback aliases, for example 127.0.10.10:80, 127.0.10.15:80, 127.0.10.30:80, and 127.0.10.40:80.
Nothing is listening on 127.0.20.4:80.
Investigation
I patched net.Server.prototype.listen to log listen attempts. Before trying the configured host, Vite first tries:
LISTEN_CALL:net [ 80, "0.0.0.0" ]
and that fails with EADDRINUSE.
The stack trace points to Vite's internal port availability check before the actual bind to the configured host.
From the current source, httpServerStart() calls isPortAvailable(port) before the real bind, and isPortAvailable(port) checks wildcard hosts (0.0.0.0, ::) rather than the configured server.host.
Expected behavior
If server.host is a specific IP, I would expect Vite to consider the port available when that exact host + port is free, even if the same port is in use on other local IPs.
Why this seems incorrect
The docs say server.host specifies which IP addresses the server should listen on. In this case, Vite appears to reject the port based on wildcard availability instead of the requested host+port combination.
Reproduction (can't post a link for this, sorry. Needs to be tested with different hosts)
|
// Pre-check port availability on wildcard addresses (0.0.0.0, ::) |
Steps to reproduce
-
Add these entries to /etc/hosts if needed:
127.0.20.4 vite-test.local
127.0.10.10 busy-a.local
127.0.10.15 busy-b.local
127.0.10.30 busy-c.local
127.0.10.40 busy-d.local
-
Start any HTTP servers on port 80 for the following loopback aliases:
127.0.10.10:80
127.0.10.15:80
127.0.10.30:80
127.0.10.40:80
-
Verify that nothing is listening on 127.0.20.4:80.
-
Run:
npm install
npm run dev
-
Observe that Vite fails with:
Error: Port 80 is already in use
-
For comparison, binding directly to 127.0.20.4:80 with a plain Bun server works.
System Info
Vite 8.0.3
Bun 1.3.6 (also tested on Node.js v25.2.1, same error)
Linux
Used Package Manager
bun
Logs
demo-vue dev $ bunx --bun vite
│ error when starting dev server:
│ Error: Port 80 is already in use
│ at httpServerStart (/home/blabla/node_modules/vite/dist/node/chunks/node.js:10635:29)
│ at async startServer (/home/blabla/node_modules/vite/dist/node/chunks/node.js:26219:36)
│ at async listen (/home/blabla/node_modules/vite/dist/node/chunks/node.js:26040:10)
│ at async (/home/blabla/node_modules/vite/dist/node/cli.js:722:16)
│ at processTicksAndRejections (native:7:39)
└─ Exited with code 1
error: script "dev:vue" exited with code 1
Validations
Describe the bug
When
server.hostis set to a specific IP address, Vite still rejects the configured port if that port is already in use on a different local interface.In my case, I set
server.host = '127.0.20.4',server.port = 80, andserver.strictPort = true. The address127.0.20.4:80is actually free, and I can bind to it successfully with a plain Bun server. However, Vite exits with:Error: Port 80 is already in useMinimal config
vite.config.jsReproduction context
I also have other local services listening on port 80, but on different loopback aliases, for example
127.0.10.10:80,127.0.10.15:80,127.0.10.30:80, and127.0.10.40:80.Nothing is listening on
127.0.20.4:80.Investigation
I patched
net.Server.prototype.listento log listen attempts. Before trying the configured host, Vite first tries:LISTEN_CALL:net [ 80, "0.0.0.0" ]and that fails with
EADDRINUSE.The stack trace points to Vite's internal port availability check before the actual bind to the configured host.
From the current source,
httpServerStart()callsisPortAvailable(port)before the real bind, andisPortAvailable(port)checks wildcard hosts (0.0.0.0,::) rather than the configuredserver.host.Expected behavior
If
server.hostis a specific IP, I would expect Vite to consider the port available when that exacthost + portis free, even if the same port is in use on other local IPs.Why this seems incorrect
The docs say
server.hostspecifies which IP addresses the server should listen on. In this case, Vite appears to reject the port based on wildcard availability instead of the requested host+port combination.Reproduction (can't post a link for this, sorry. Needs to be tested with different hosts)
vite/packages/vite/src/node/http.ts
Line 230 in 73bb1ba
Steps to reproduce
Add these entries to /etc/hosts if needed:
127.0.20.4 vite-test.local
127.0.10.10 busy-a.local
127.0.10.15 busy-b.local
127.0.10.30 busy-c.local
127.0.10.40 busy-d.local
Start any HTTP servers on port 80 for the following loopback aliases:
127.0.10.10:80
127.0.10.15:80
127.0.10.30:80
127.0.10.40:80
Verify that nothing is listening on 127.0.20.4:80.
Run:
npm install
npm run dev
Observe that Vite fails with:
Error: Port 80 is already in use
For comparison, binding directly to 127.0.20.4:80 with a plain Bun server works.
System Info
Used Package Manager
bun
Logs
demo-vue dev $ bunx --bun vite
│ error when starting dev server:
│ Error: Port 80 is already in use
│ at httpServerStart (/home/blabla/node_modules/vite/dist/node/chunks/node.js:10635:29)
│ at async startServer (/home/blabla/node_modules/vite/dist/node/chunks/node.js:26219:36)
│ at async listen (/home/blabla/node_modules/vite/dist/node/chunks/node.js:26040:10)
│ at async (/home/blabla/node_modules/vite/dist/node/cli.js:722:16)
│ at processTicksAndRejections (native:7:39)
└─ Exited with code 1
error: script "dev:vue" exited with code 1
Validations