{"record":{"id":"0c75e1e13955fe5c","repo":"vitejs/vite","slug":"no-available-ephemeral-port-found","errorCode":null,"errorMessage":"No available ephemeral port found","messagePattern":"No available ephemeral port found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/http.ts","lineNumber":263,"sourceCode":"}\n\nconst MAX_PORT = 65535\n\nexport async function httpServerStart(\n  httpServer: HttpServer,\n  serverOptions: {\n    port: number\n    strictPort: boolean | undefined\n    host: string | undefined\n    logger: Logger\n  },\n): Promise<number> {\n  const { port: startPort, strictPort, host, logger } = serverOptions\n\n  if (startPort === 0) {\n    const port = await getAvailableEphemeralPort(host)\n    if (port == null) {\n      throw new Error('No available ephemeral port found')\n    }\n\n    const result = await tryBindServer(httpServer, port, host)\n    if (result.success) {\n      return port\n    }\n    if (result.error.code !== 'EADDRINUSE') {\n      throw result.error\n    }\n    // this can happen if the port was listened by other process between getAvailableEphemeralPort and tryBindServer\n    throw new Error(`Port ${port} is already in use`)\n  }\n\n  for (let port = startPort; port <= MAX_PORT; port++) {\n    // Pre-check port availability on wildcard addresses (0.0.0.0, ::)\n    // so that we avoid conflicts with other servers listening on all interfaces\n    const portAvailableOnWildcard = await isPortAvailable(port)\n","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/vitejs/vite/blob/b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab/packages/vite/src/node/http.ts#L245-L281","documentation":"When server.port is 0 (ephemeral), Vite calls getAvailableEphemeralPort to find a free port. If it returns null (no free port in the ephemeral range after retries), Vite throws 'No available ephemeral port found'. A subsequent bind race can also surface the related 'Port X is already in use' message.","triggerScenarios":"Starting the dev server with server.port: 0 on a machine where the ephemeral range (typically 1024-65535) is exhausted - all candidate ports are bound, in TIME_WAIT, or otherwise unavailable.","commonSituations":"Heavy containerized CI with many concurrent Vite instances; systems with very low ephemeral port ranges (net.ipv4.ip_local_port_range); exhausted ports due to crashed processes holding sockets.","solutions":["Free up ports: stop orphan processes or raise the OS ephemeral range (sysctl net.ipv4.ip_local_port_range).","Wait for TIME_WAIT sockets to recycle (default ~60s) before restarting.","Pin an explicit server.port with strictPort: false so Vite can scan upward."],"exampleFix":"// before\nserver: { port: 0, strictPort: true }\n// after\nserver: { port: 5173, strictPort: false }","handlingStrategy":"retry","validationCode":"function detectPortExhaustion(host) {\n  return new Promise((resolve) => {\n    require('net').createServer().once('error', () => resolve(true)).listen(0, host, () => resolve(false));\n  });\n}","typeGuard":null,"tryCatchPattern":"let attempts = 0;\nasync function startServer(server) {\n  while (attempts < 3) {\n    try { return await server.listen(); }\n    catch (e) {\n      if (/No available ephemeral port/.test(String(e.message)) && attempts < 2) { attempts++; await new Promise((r) => setTimeout(r, 1000)); continue; }\n      throw e;\n    }\n  }\n}","preventionTips":["Raise the OS ephemeral port range on CI runners.","Reuse a single dev server across watch tasks instead of spawning many.","Pin server.port to a known-free value when possible."],"tags":["network","dev-server","port","ephemeral"],"backgroundTag":null,"analyzedSha":"b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab","analyzedAt":"2026-08-11T11:49:19.515Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}