{"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":"Error","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/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-dev/vite/plugins/prerender.ts#L543-L578","documentation":"Thrown by startPreviewServer() during the prerender data flow when Vite's preview() call rejects. The original error is preserved on the `cause` property so the underlying Vite failure (port binding, missing build output, invalid config) is inspectable. This is a wrapper that contextualizes a low-level Vite failure inside the React Router prerender pipeline.","triggerScenarios":"Calling the prerender pipeline (build with prerender config in data mode) which internally invokes vite.preview({ configFile, logLevel:'silent', preview:{ port:0, open:false } }). Any rejection from vite.preview() — e.g. no built dist to preview, a broken vite.config, EADDRINUSE despite port:0 (rare), or an invalid configFile path — is caught and re-thrown as this error.","commonSituations":"Running a prerender build without first running a successful production build (dist/ missing or stale). A vite.config.ts that throws at preview time (custom preview plugins). Upgrading Vite to a version whose preview API changed. CI environments where the build step was skipped or cached output was pruned.","solutions":["Inspect err.cause for the real Vite error (port, config, or missing artifacts) and address that first.","Run `pnpm build` (or the project's production build) before invoking the prerender step so dist/ exists.","Validate vite.config.ts loads cleanly with `vite preview` standalone to isolate plugin/config errors.","Clear stale build output (`pnpm run clean` / remove dist and .vite) and rebuild.","Ensure the configFile referenced by the resolved Vite config exists and has no syntax/import errors."],"exampleFix":"// before: prerender invoked on a project whose dist/ was never built\n// run a production build first\n//   pnpm build\n// then re-run the prerender pipeline\n\n// if a custom vite.config breaks preview, isolate it:\n//   npx vite preview --config vite.config.ts\n// fix the reported error, then retry prerender","handlingStrategy":"try-catch","validationCode":"// before invoking prerender, confirm a build exists\nimport { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nconst distExists = existsSync(resolve(process.cwd(), 'build', 'client')) || existsSync(resolve(process.cwd(), 'dist'));\nif (!distExists) throw new Error('Run `pnpm build` before prerendering.');","typeGuard":null,"tryCatchPattern":"try {\n  await runPrerenderPipeline();\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Prerender: Failed to start Vite preview server') && e.cause) {\n    console.error('Underlying Vite error:', e.cause);\n  }\n  throw e;\n}","preventionTips":["Always run the production build before prerender in CI scripts.","Treat err.cause as the source of truth — the wrapper message alone is not actionable.","Pin Vite to the version range declared in @react-router/dev peerDependencies."],"tags":["prerender","vite","build","preview-server"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}