remix-run/react-router · error · Error
React Router presets must have a `name` property defined.
Error message
React Router presets must have a `name` property defined.
What it means
Thrown during React Router config resolution when iterating reactRouterUserConfig.presets and a preset object lacks a name property (preset.name is falsy). Presets are an array in react-router.config.ts; each must declare a name for identification and deduplication. The check runs after the user config is loaded, validated, and deep-frozen, so it fires during build/dev startup before the preset's reactRouterConfig callback is invoked.
Source
Thrown at packages/react-router-dev/config/config.ts:494
if (validateConfig) {
const error = validateConfig(reactRouterUserConfig);
if (error) {
return err(error);
}
}
} catch (error) {
return err(`Error loading ${reactRouterConfigFile}: ${error}`);
}
}
// Prevent mutations to the user config
reactRouterUserConfig = deepFreeze(cloneDeep(reactRouterUserConfig));
let presets: ReactRouterConfig[] = (
await Promise.all(
(reactRouterUserConfig.presets ?? []).map(async (preset) => {
if (!preset.name) {
throw new Error(
"React Router presets must have a `name` property defined.",
);
}
if (!preset.reactRouterConfig) {
return null;
}
let configPreset: ReactRouterConfig = omit(
await preset.reactRouterConfig({ reactRouterUserConfig }),
excludedConfigPresetKeys,
);
return configPreset;
}),
)
).filter(function isNotNull<T>(value: T | null): value is T {
return value !== null;View on GitHub (pinned to 1fd704a7da)
Solutions
- Add a unique name string to every preset in react-router.config.ts: presets: [{ name: 'my-preset', reactRouterConfig: () => ({...}) }].
- If importing a preset from a package, ensure its exported object includes name, or wrap it: { name: 'pkg', ...importedPreset }.
- Remove the offending preset if it is unused.
- Lint your config by logging presets.map(p => p.name) before build to catch missing names early.
Example fix
// before (react-router.config.ts)
export default {
presets: [{ reactRouterConfig: () => ({ ssr: true }) }],
} satisfies ReactRouterConfig;
// after
export default {
presets: [{ name: 'ssr-preset', reactRouterConfig: () => ({ ssr: true }) }],
} satisfies ReactRouterConfig; Defensive patterns
Strategy: validation
Validate before calling
// Validate presets before build/dev
function presetsAreNamed(presets: any[]): boolean {
return Array.isArray(presets) && presets.every((p) => typeof p?.name === 'string' && p.name.length > 0);
}
const cfg = (await import('./react-router.config.ts')).default;
if (!presetsAreNamed(cfg.presets ?? [])) {
throw new Error('Every preset must define a unique `name`.');
} Type guard
interface ReactRouterPreset { name: string; reactRouterConfig?: (ctx: any) => any | Promise<any>; }
function isNamedPreset(p: unknown): p is ReactRouterPreset {
return typeof p === 'object' && p !== null && typeof (p as any).name === 'string' && (p as any).name.length > 0;
} Prevention
- Always specify name when authoring presets in react-router.config.ts.
- Add a config lint step to your CI that asserts every preset has a name.
- When wrapping imported presets, spread them after setting name: { name: 'pkg', ...imported }.
- Document the name requirement in your preset package's README.
When it happens
Trigger: Authoring react-router.config.ts with presets: [{ reactRouterConfig: () => ({...}) }] (name omitted); spreading an object that drops name; a preset factory returning an object without name; importing a preset from a package whose default export is unnamed.
Common situations: Converting a flat config into presets and forgetting the name field; copy-pasting a preset example that omitted name; upgrading a preset package whose API changed to require name; community preset without a name.
Related errors
- Could not find package.json in ${rootDirectory} or any of it
- Unable to define routes with duplicate route id: "${id}"
- React Router Vite plugin not found in Vite config
- The React Router Vite plugin requires the use of a Vite conf
- ${configResult.error}
AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12).
Data as JSON: /api/errors/f64d40a1a05d8124.
Report an issue: GitHub.