remix-run/react-router · error · Error
Prerender: Failed to start Vite preview server
Error message
Prerender: Failed to start Vite preview server
What it means
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.
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 1fd704a7da)
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.
Example fix
// before: prerender invoked on a project whose dist/ was never built // run a production build first // pnpm build // then re-run the prerender pipeline // if a custom vite.config breaks preview, isolate it: // npx vite preview --config vite.config.ts // fix the reported error, then retry prerender
Defensive patterns
Strategy: try-catch
Validate before calling
// before invoking prerender, confirm a build exists
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
const distExists = existsSync(resolve(process.cwd(), 'build', 'client')) || existsSync(resolve(process.cwd(), 'dist'));
if (!distExists) throw new Error('Run `pnpm build` before prerendering.'); Try / catch
try {
await runPrerenderPipeline();
} catch (e) {
if (e instanceof Error && e.message.startsWith('Prerender: Failed to start Vite preview server') && e.cause) {
console.error('Underlying Vite error:', e.cause);
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Prerender: No resolved URL is available from the Vite previe
- React Router Vite plugin not found in Vite config
- Custom Vite manifest paths are not supported
- Prerender (data): Received a ${response.status} status code
- Prerender (resource): Received a ${response.status} status c
AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12).
Data as JSON: /api/errors/fcd9d19c4a981b33.
Report an issue: GitHub.