remix-run/react-router · error
The "@vitejs/plugin-rsc" plugin should be placed after the…
Error message
The "@vitejs/plugin-rsc" plugin should be placed after the React Router RSC plugin in your Vite config
What it means
In RSC Framework Mode (`unstable_reactRouterRSC`), plugin order matters: the React Router RSC plugin (`react-router/rsc`) must come before `@vitejs/plugin-rsc` (`rsc`) in the plugins array so RR can register its virtual modules and transforms ahead of the RSC compiler. A `validate-plugin-order` plugin compares plugin indices in `configResolved` and throws when `@vitejs/plugin-rsc` is placed first.
Solutions
- Reorder vite.config.ts so `reactRouter()` comes first and `@vitejs/plugin-rsc()` after it
- Use the RSC template (`rsc-vite-framework`) as the reference ordering
- Also verify `@mdx-js/rollup` sits before the React Router plugin if present (checked in the same validator)
Example fix
// before (vite.config.ts)
plugins: [rsc(), reactRouter()],
// after
import { reactRouter } from '@react-router/dev/vite';
import { rsc } from '@vitejs/plugin-rsc';
plugins: [reactRouter(), rsc()], Defensive patterns
Strategy: validation
Validate before calling
// Assert plugin order before exporting the config
const plugins = [mdx(), reactRouter(), rsc()];
const idx = (name: string) => plugins.findIndex((p: any) => p.name?.includes(name));
if (idx('rsc') >= 0 && idx('rsc') < idx('react-router')) {
throw new Error('@vitejs/plugin-rsc must come after reactRouter()');
}
if (idx('@mdx-js/rollup') >= 0 && idx('@mdx-js/rollup') > idx('react-router')) {
throw new Error('@mdx-js/rollup must come before reactRouter()');
}
export default defineConfig({ plugins }); Try / catch
try {
await build();
} catch (e) {
if (e instanceof Error && e.message.includes('should be placed after')) {
// reorder plugins per the message and rebuild
}
} Prevention
- Use the official RSC template's plugin ordering as canonical
- Put `mdx()` first, `reactRouter()` next, `rsc()` last in RSC Framework Mode
- Re-run `react-router typegen` after any config reorder to catch it cheaply
When it happens
Trigger: Adding `rsdc()`/`@vitejs/plugin-rsc()` to `plugins: [...]` before `reactRouter({ unstable_reactRouterRSC: ... })`; auto-generated configs or templates inserting the RSC plugin at the top; spreading user plugins before the RR plugin in a shared config.
Common situations: Hand-editing vite.config.ts while trying RSC mode; copying plugin arrays from docs where order was different; merging configs where `...restPlugins` lands ahead of `reactRouter()`.
Related errors
- When using the React Router `basename` and the Vite `base`…
- Custom Vite manifest paths are not supported
- Error loading
- React Router config loading requires Vite's __config_loader…
- React Router Vite plugin not found in Vite config
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/7ccd9b0d89a230b0.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router-dev/vite/plugins/validate-plugin-order.ts:21
export function validatePluginOrder(): Vite.Plugin {
return {
name: "react-router:validate-plugin-order",
configResolved(viteConfig) {
let pluginIndex = (pluginName: string | string[]) => {
pluginName = Array.isArray(pluginName) ? pluginName : [pluginName];
return viteConfig.plugins.findIndex((plugin) =>
pluginName.includes(plugin.name),
);
};
let reactRouterRscPluginIndex = pluginIndex("react-router/rsc");
let viteRscPluginIndex = pluginIndex("rsc");
if (
reactRouterRscPluginIndex >= 0 &&
viteRscPluginIndex >= 0 &&
reactRouterRscPluginIndex > viteRscPluginIndex
) {
throw new Error(
`The "@vitejs/plugin-rsc" plugin should be placed after the React Router RSC plugin in your Vite config`,
);
}
let reactRouterPluginIndex = pluginIndex([
"react-router",
"react-router/rsc",
]);
let mdxPluginIndex = pluginIndex("@mdx-js/rollup");
if (mdxPluginIndex >= 0 && mdxPluginIndex > reactRouterPluginIndex) {
throw new Error(
`The "@mdx-js/rollup" plugin should be placed before the React Router plugin in your Vite config`,
);
}
},
};
}
View on GitHub (pinned to 6beaca3952)