{"record":{"id":"fcd9d19c4a981b33","repo":"remix-run/react-router","slug":"prerender-failed-to-start-vite-preview-server","errorCode":null,"errorMessage":"Prerender: Failed to start Vite preview server","messagePattern":"Prerender: Failed to start Vite preview server","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugins/prerender.ts","lineNumber":561,"sourceCode":"  });\n}\n\nasync function startPreviewServer(\n  viteConfig: Vite.ResolvedConfig,\n): Promise<Vite.PreviewServer> {\n  const vite = await import(\"vite\");\n\n  try {\n    return await vite.preview({\n      configFile: viteConfig.configFile,\n      logLevel: \"silent\",\n      preview: {\n        port: 0,\n        open: false,\n      },\n    });\n  } catch (error) {\n    throw new Error(\"Prerender: Failed to start Vite preview server\", {\n      cause: error,\n    });\n  }\n}\n\nfunction getResolvedUrl(previewServer: Vite.PreviewServer): URL {\n  const baseUrl = previewServer.resolvedUrls?.local[0];\n\n  if (!baseUrl) {\n    throw new Error(\n      \"Prerender: No resolved URL is available from the Vite preview server\",\n    );\n  }\n\n  return new URL(baseUrl);\n}\n","sourceCodeStart":543,"sourceCodeEnd":578,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/vite/plugins/prerender.ts#L543-L578","documentation":"The prerender plugin serves your built app through a temporary Vite preview server (port 0, silent logging) and issues requests against it. If `vite.preview()` throws — bad build output, config errors, port/host problems — the error is wrapped with this message and the original error attached as `cause`. The prerender cannot proceed without a server to render through.","triggerScenarios":"`vite.preview()` rejecting: missing or malformed `build/client` output (build step skipped or failed silently); invalid `preview` config in vite.config.ts; `configFile` pointing at a config that errors when loaded in preview mode; port allocation failures on constrained CI.","commonSituations":"Running prerender without a preceding successful build; custom `vite.preview` settings (host, strictPort, https) that break headless startup; CI sandboxes blocking listen() on the requested host.","solutions":["Inspect `error.cause` — it carries the underlying Vite error","Ensure the client (and server) build completed successfully before prerendering","Remove or scope custom `preview` config in vite.config.ts that conflicts with the plugin's `port: 0, open: false` settings","On CI, verify the environment allows binding a loopback port"],"exampleFix":"// before (vite.config.ts) — conflicting preview config\npreview: { port: 4173, strictPort: true, host: '0.0.0.0' },\n\n// after — let the prerender plugin pick an ephemeral port\n// (remove the custom preview block or drop strictPort)","handlingStrategy":"try-catch","validationCode":"// Confirm build output exists before prerendering\nimport fs from 'node:fs';\nfor (const p of ['build/client/index.html', 'build/server/index.js']) {\n  if (!fs.existsSync(p)) throw new Error(`Missing ${p} — run the build first`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await startPreviewServer(viteConfig);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Failed to start Vite preview server')) {\n    // inspect e.cause — the underlying Vite error — before rethrowing\n    console.error(e.cause);\n  }\n  throw e;\n}","preventionTips":["Chain prerender after a successful `react-router build` in CI scripts","Avoid `strictPort`/fixed hosts in `preview` config","Keep Vite version compatible with @react-router/dev's peer range"],"tags":["prerender","ssg","vite","preview-server","build"],"backgroundTag":"vite-server-start-failed","analyzedSha":"6beaca39526d5716c3c112ebb0782765baa5a9ce","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}