remix-run/react-router · error · Error
Custom Vite manifest paths are not supported
Error message
Custom Vite manifest paths are not supported
What it means
When React Router resolves the Vite config for its child compilers, it checks `viteConfig.build.manifest`. The framework reads the Vite manifest from its well-known default location to map route modules to built assets, so a custom manifest path string is rejected outright. This is a compatibility guard: RR post-processes the manifest itself and cannot follow a relocated one.
Solutions
- Remove the custom string from `build.manifest` in vite.config.ts and let it stay `true`/unset so Vite emits `.vite/manifest.json` at the default path
- If you need the manifest for another tool, read it from `build/assets/.vite/manifest.json` after the build instead of relocating it
- Scope any custom Vite build config used by other apps away from the React Router app's vite.config.ts
Example fix
// before (vite.config.ts)
export default defineConfig({
build: { manifest: 'dist/rr-manifest.json' },
});
// after
export default defineConfig({
build: { manifest: true }, // default .vite/manifest.json location
}); Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight check before running react-router build
import type { UserConfig } from 'vite';
const cfg: UserConfig = { /* ... */ };
if (typeof cfg.build?.manifest === 'string') {
throw new Error('React Router does not support a custom build.manifest path');
}
export default cfg; Type guard
const hasCustomManifestPath = (cfg: { build?: { manifest?: unknown } }): boolean =>
typeof cfg.build?.manifest === 'string'; Try / catch
try {
await build();
} catch (e) {
if (e instanceof Error && e.message.includes('manifest paths are not supported')) {
console.error('Remove build.manifest path from vite.config.ts and retry');
process.exit(1);
}
throw e;
} Prevention
- Never set `build.manifest` to a string in a React Router project
- Consume the manifest at its default path `build/client/.vite/manifest.json` in downstream tooling
- Lint shared Vite configs to forbid `build.manifest` string overrides
When it happens
Trigger: Setting `build.manifest: 'custom/manifest.json'` (any string) in vite.config.ts while the React Router Vite plugin is active; copying a shared Vite config from a non-React Router project that customizes the manifest path; enabling `build.manifest` with a path via a shared config preset.
Common situations: Teams reusing an existing Vite config that set `build.manifest` for their own asset pipeline; CI configs that centralized `manifest: 'dist/manifest.json'`; upgrading to Framework Mode while keeping legacy Vite build options.
Related errors
- React Router Vite plugin not found in Vite config
- The React Router Vite plugin requires the use of a Vite…
- Could not find a root route module in the app directory as
- Error loading
- Prerender: Failed to start Vite preview server
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/1255f066a5c50266.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router-dev/vite/plugin.ts:126
root,
plugins,
}: {
configFile?: string;
mode?: string;
plugins?: Vite.Plugin[];
root: string;
}) {
let vite = getVite();
let viteConfig = await vite.resolveConfig(
{ mode, configFile, root, plugins },
"build", // command
"production", // default mode
"production", // default NODE_ENV
);
if (typeof viteConfig.build.manifest === "string") {
throw new Error("Custom Vite manifest paths are not supported");
}
return viteConfig;
}
export function extractPluginContext(
viteConfig: Vite.ResolvedConfig | Vite.UserConfig,
) {
return viteConfig["__reactRouterPluginContext" as keyof typeof viteConfig] as
| ReactRouterPluginContext
| undefined;
}
const SERVER_ONLY_ROUTE_EXPORTS = ["loader", "action", "middleware", "headers"];
const CLIENT_NON_COMPONENT_EXPORTS = [
"clientAction",
"clientLoader",
"clientMiddleware",View on GitHub (pinned to 6beaca3952)