vitejs/vite · error · Error

Port ${port} is already in use

Error message

Port ${port} is already in use

What it means

Thrown by `httpServer` port resolution when `strictPort: true` and the requested port cannot be bound (the bind attempt returns `EADDRINUSE`). With strictPort Vite refuses to silently move to another port, so it surfaces the conflict directly. The throw is at http.ts:252, after re-binding confirms the failure is an in-use error.

Source

Thrown at packages/vite/src/node/http.ts:252

    // If port is not available on a wildcard address but strictPort is set,
    // we still try binding directly before giving up.
    if (strictPort) {
      const result = await tryBindServer(httpServer, port, host)
      if (result.success) {
        if (!portAvailableOnWildcard) {
          logger.warn(
            colors.yellow(
              `Port ${port} is in use on a wildcard address, but ${host ?? 'localhost'}:${port} is available. ` +
                `There may be another server running on a wildcard IP on port ${port}.`,
            ),
          )
        }
        return port
      }
      if (result.error.code !== 'EADDRINUSE') {
        throw result.error
      }
      throw new Error(`Port ${port} is already in use`)
    }

    if (portAvailableOnWildcard) {
      const result = await tryBindServer(httpServer, port, host)
      if (result.success) {
        return port
      }
      if (result.error.code !== 'EADDRINUSE') {
        throw result.error
      }
    }
    logger.info(`Port ${port} is in use, trying another one...`)
  }
  throw new Error(
    `No available ports found between ${startPort} and ${MAX_PORT}`,
  )
}

View on GitHub (pinned to 89620f09af)

Solutions

  1. Free the port: find the process with `lsof -i :<port>` / `netstat -ano` and stop it, or restart your machine/WSL.
  2. Set `strictPort: false` (default) so Vite auto-increments to the next free port.
  3. Change `server.port` to a free port in the config.
  4. If the holder is your own orphaned process, run `tman kill`/`kill -9 <pid>`.

Example fix

// before
export default defineConfig({ server: { port: 5173, strictPort: true } })

// after
export default defineConfig({ server: { port: 5173, strictPort: false } })
Defensive patterns

Strategy: validation

Validate before calling

import net from 'node:net'
async function isFree(port: number, host?: string): Promise<boolean> {
  return new Promise((res) => {
    const s = net.createServer()
    s.unref().once('error', () => res(false)).listen(port, host, () => s.close(() => res(true)))
  })
}
// before createServer: if (config.server.strictPort && !(await isFree(port))) throw ...

Try / catch

try {
  await createServer(config)
} catch (e) {
  if (e instanceof Error && /already in use/.test(e.message)) {
    // free the port or switch config.server.port / strictPort and retry once
  } else throw e
}

Prevention

When it happens

Trigger: Starting `createServer`/`createPreviewServer` with `server.strictPort: true` (or `preview.strictPort: true`) while the configured `server.port` is already bound by another process.

Common situations: A previous dev server didn't shut down cleanly; another app (or a second Vite instance) holds the port; Docker/WSL port forwarding conflicts; running multiple projects on port 5173/3000.

Related errors


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/1b93d9782900a563.json. Report an issue: GitHub.