{"record":{"id":"f64d40a1a05d8124","repo":"remix-run/react-router","slug":"react-router-presets-must-have-a-name-property-d","errorCode":null,"errorMessage":"React Router presets must have a `name` property defined.","messagePattern":"React Router presets must have a `name` property defined\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/config/config.ts","lineNumber":494,"sourceCode":"      if (validateConfig) {\n        const error = validateConfig(reactRouterUserConfig);\n        if (error) {\n          return err(error);\n        }\n      }\n    } catch (error) {\n      return err(`Error loading ${reactRouterConfigFile}: ${error}`);\n    }\n  }\n\n  // Prevent mutations to the user config\n  reactRouterUserConfig = deepFreeze(cloneDeep(reactRouterUserConfig));\n\n  let presets: ReactRouterConfig[] = (\n    await Promise.all(\n      (reactRouterUserConfig.presets ?? []).map(async (preset) => {\n        if (!preset.name) {\n          throw new Error(\n            \"React Router presets must have a `name` property defined.\",\n          );\n        }\n\n        if (!preset.reactRouterConfig) {\n          return null;\n        }\n\n        let configPreset: ReactRouterConfig = omit(\n          await preset.reactRouterConfig({ reactRouterUserConfig }),\n          excludedConfigPresetKeys,\n        );\n\n        return configPreset;\n      }),\n    )\n  ).filter(function isNotNull<T>(value: T | null): value is T {\n    return value !== null;","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/config/config.ts#L476-L512","documentation":"While resolving react-router.config.ts, every entry of the presets array must have a name property (presets are identified by name when merged and reported). During config resolution the loader maps over presets and throws on the first entry lacking name, which fails the dev server or build startup.","triggerScenarios":"Writing presets: [{}] (empty object), or presets: [{ reactRouterConfig: ... }] with the config function but no name; JS configs or `any` casts bypassing the TypeScript Preset type that would normally flag it.","commonSituations":"Adding a first preset to react-router.config.ts; copy-pasting preset examples that omit name; refactors that rename or drop the name field.","solutions":["Add a name to every entry in the presets array","Scan the array for accidental empty objects or stray trailing entries","Restart the dev server after saving react-router.config.ts"],"exampleFix":"// before: react-router.config.ts\nexport default {\n  presets: [\n    { reactRouterConfig: async () => ({ ssr: true }) },\n  ],\n};\n\n// after\nexport default {\n  presets: [\n    {\n      name: \"ssr-on\",\n      reactRouterConfig: async () => ({ ssr: true }),\n    },\n  ],\n};","handlingStrategy":"type-guard","validationCode":"import type { Preset, ReactRouterConfig } from \"@react-router/dev\";\n\nfunction isNamedPreset(p: Preset): p is Preset & { name: string } {\n  return typeof p.name === \"string\" && p.name.length > 0;\n}\n\nexport default {\n  presets: myPresets.every(isNamedPreset) ? myPresets : (() => {\n    throw new Error(\"Every preset needs a non-empty `name`\");\n  })(),\n} satisfies ReactRouterConfig;","typeGuard":"interface PresetLike {\n  name?: unknown;\n  reactRouterConfig?: unknown;\n}\n\nfunction isNamedPreset(p: PresetLike): p is { name: string } & PresetLike {\n  return typeof p.name === \"string\" && p.name.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Type react-router.config.ts properly (satisfies ReactRouterConfig) so TypeScript flags missing name","Start from the documented preset example which includes name","Give presets stable, descriptive names — they identify the preset in merged output"],"tags":["config","presets","framework-mode"],"backgroundTag":"invalid-config-value","analyzedSha":"6beaca39526d5716c3c112ebb0782765baa5a9ce","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}