{"record":{"id":"338dfc83526d0156","repo":"facebook/docusaurus","slug":"route-route-path-has-conflicting-props-declared","errorCode":null,"errorMessage":"Route ${route.path} has conflicting props declared using both route.modules and route.props APIs for keys: ${conflictingPropNames.join(', ')}\\nThis is not permitted, otherwise one prop would override the over.","messagePattern":"Route (.+?) has conflicting props declared using both route\\.modules and route\\.props APIs for keys: (.+?)\\\\nThis is not permitted, otherwise one prop would override the over\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/docusaurus/src/server/codegen/codegenRoutes.ts","lineNumber":413,"sourceCode":"    generateRoutePropFilename(route),\n  );\n  const modulePath = path.posix.join(generatedFilesDir, relativePath);\n  const aliasedPath = path.posix.join('@generated', relativePath);\n\n  await generate(generatedFilesDir, modulePath, moduleContent);\n  return aliasedPath;\n}\n\nfunction ensureNoPropsConflict(route: RouteConfig) {\n  if (!route.props && !route.modules) {\n    return;\n  }\n  const conflictingPropNames = _.intersection(\n    Object.keys(route.props ?? {}),\n    Object.keys(route.modules ?? {}),\n  );\n  if (conflictingPropNames.length > 0) {\n    throw new Error(\n      `Route ${\n        route.path\n      } has conflicting props declared using both route.modules and route.props APIs for keys: ${conflictingPropNames.join(\n        ', ',\n      )}\\nThis is not permitted, otherwise one prop would override the over.`,\n    );\n  }\n}\n\nasync function preprocessRouteProps({\n  generatedFilesDir,\n  route,\n  plugin,\n}: {\n  generatedFilesDir: string;\n  route: RouteConfig;\n  plugin: PluginIdentifier;\n}): Promise<RouteConfig> {","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus/src/server/codegen/codegenRoutes.ts#L395-L431","documentation":"Thrown by `ensureNoPropsConflict(route)` when the same prop key is declared both in `route.props` and `route.modules`. These two APIs feed the same prop namespace on the rendered component, so a duplicate key would silently overwrite one value; Docusaurus rejects it up front. (Note: the message has a known typo — 'override the over' — but the meaning is clear.)","triggerScenarios":"A plugin route (or a user-authored route via the routing API) declares `props: { foo: ... }` and `modules: { foo: ... }` for the same key `foo`.","commonSituations":"Plugin author migrates from `props` to `modules` (or vice-versa) and forgets to remove the old key; copy-paste between routes; merging two plugins' route configs that both inject the same prop name (e.g. `auth`, `data`).","solutions":["Inspect the conflicting key names in the error message and remove the duplicate from either `props` or `modules`.","Prefer `modules` for code-split lazy-loaded values and `props` for inline serializable values — keep the same key in only one.","Rename one of the colliding keys if both are genuinely needed.","Add a small assertion in your plugin's route builder to catch this in dev: `_.intersection(Object.keys(route.props??{}), Object.keys(route.modules??{})).length === 0`."],"exampleFix":"// before\nexport default {\n  path: '/x',\n  component: '@theme/Page',\n  props: { data: 1 },\n  modules: { data: '@generated/data.js' }, // conflicts\n};\n// after\nexport default {\n  path: '/x',\n  component: '@theme/Page',\n  modules: { data: '@generated/data.js' },\n};","handlingStrategy":"validation","validationCode":"const conflict = _.intersection(Object.keys(route.props ?? {}), Object.keys(route.modules ?? {}));\nif (conflict.length > 0) throw new Error(`Conflicting prop keys: ${conflict.join(', ')}`);","typeGuard":"function hasNoPropsConflict(route: any): boolean {\n  const pk = Object.keys(route?.props ?? {});\n  const mk = Object.keys(route?.modules ?? {});\n  return pk.every((k) => !mk.includes(k));\n}","tryCatchPattern":null,"preventionTips":["Pick one prop API (`props` or `modules`) per key — never both.","Add a plugin-dev assertion using the type guard above.","Code-review route configs from migrated plugins for leftover duplicate keys."],"tags":["routing","codegen","plugins","validation"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}