remix-run/react-router · error
Prerender: Failed to start Vite preview server
Error message
Prerender: Failed to start Vite preview server
What it means
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.
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
Example fix
// before (vite.config.ts) — conflicting preview config
preview: { port: 4173, strictPort: true, host: '0.0.0.0' },
// after — let the prerender plugin pick an ephemeral port
// (remove the custom preview block or drop strictPort) Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm build output exists before prerendering
import fs from 'node:fs';
for (const p of ['build/client/index.html', 'build/server/index.js']) {
if (!fs.existsSync(p)) throw new Error(`Missing ${p} — run the build first`);
} Try / catch
try {
await startPreviewServer(viteConfig);
} catch (e) {
if (e instanceof Error && e.message.includes('Failed to start Vite preview server')) {
// inspect e.cause — the underlying Vite error — before rethrowing
console.error(e.cause);
}
throw e;
} Prevention
- 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
When it happens
Trigger: `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.
Common situations: 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.
Related errors
- Prerender: No resolved URL is available from the Vite…
- ⚠️ Paths with dynamic/splat params cannot be prerendered…
- Prerender (data): Received a
- Prerender (html): Received a
- Prerender: Request failed for
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/fcd9d19c4a981b33.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router-dev/vite/plugins/prerender.ts:561
});
}
async function startPreviewServer(
viteConfig: Vite.ResolvedConfig,
): Promise<Vite.PreviewServer> {
const vite = await import("vite");
try {
return await vite.preview({
configFile: viteConfig.configFile,
logLevel: "silent",
preview: {
port: 0,
open: false,
},
});
} catch (error) {
throw new Error("Prerender: Failed to start Vite preview server", {
cause: error,
});
}
}
function getResolvedUrl(previewServer: Vite.PreviewServer): URL {
const baseUrl = previewServer.resolvedUrls?.local[0];
if (!baseUrl) {
throw new Error(
"Prerender: No resolved URL is available from the Vite preview server",
);
}
return new URL(baseUrl);
}
View on GitHub (pinned to 6beaca3952)