{"record":{"id":"b6f131d3fb9296f7","repo":"remix-run/react-router","slug":"unable-to-define-routes-with-duplicate-route-id-b6f131","errorCode":null,"errorMessage":"Unable to define routes with duplicate route id: \"${route.id}\"","messagePattern":"Unable to define routes with duplicate route id: \"(.+?)\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-remix-routes-option-adapter/defineRoutes.ts","lineNumber":103,"sourceCode":"      // route(path, file, options, children)\n      // route(path, file, options)\n      options = optionsOrChildren || {};\n    }\n\n    let route: RouteManifestEntry = {\n      path: path ? path : undefined,\n      index: options.index ? true : undefined,\n      caseSensitive: options.caseSensitive ? true : undefined,\n      id: options.id || createRouteId(file),\n      parentId:\n        parentRoutes.length > 0\n          ? parentRoutes[parentRoutes.length - 1].id\n          : \"root\",\n      file,\n    };\n\n    if (route.id in routes) {\n      throw new Error(\n        `Unable to define routes with duplicate route id: \"${route.id}\"`,\n      );\n    }\n\n    routes[route.id] = route;\n\n    if (children) {\n      parentRoutes.push(route);\n      children();\n      parentRoutes.pop();\n    }\n  };\n\n  callback(defineRoute);\n\n  alreadyReturned = true;\n\n  return routes;","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-remix-routes-option-adapter/defineRoutes.ts#L85-L121","documentation":"defineRoutes keys its manifest by route id, which defaults to createRouteId(file) — the module's file path — or an explicit options.id. Before inserting, it checks 'route.id in routes' and throws on a collision rather than letting the second definition silently overwrite the first. This guards against ambiguous route trees where two entries claim the same id.","triggerScenarios":"Two route() calls referencing the same file path (same derived id); two calls passing the same explicit id option; a helper loop generating definitions that collapse onto one file or id.","commonSituations":"Copy-pasted route definitions reusing a file; mapping a list where multiple entries render the same component file; deliberately using one module for both a pathless layout and a page without giving one a distinct id.","solutions":["Give each route a unique file path","When intentionally reusing a module, pass distinct id options: route('a', 'page.tsx', { id: 'a' }) and route('b', 'page.tsx', { id: 'b' })","Check for accidental duplicates in generated/looped route definitions"],"exampleFix":"// before\nconst routes = defineRoutes(() => {\n  route(\"about\", \"routes/page.tsx\");\n  route(\"company\", \"routes/page.tsx\"); // same file => duplicate id\n});\n\n// after\nconst routes = defineRoutes(() => {\n  route(\"about\", \"routes/page.tsx\", { id: \"about-page\" });\n  route(\"company\", \"routes/page.tsx\", { id: \"company-page\" });\n});","handlingStrategy":"validation","validationCode":"// track ids yourself and fail with a clearer message before the library does\nconst seen = new Set<string>();\nfunction assertUniqueId(id: string) {\n  if (seen.has(id)) throw new Error(`Duplicate route id: '${id}'`);\n  seen.add(id);\n}\nconst routes = defineRoutes(() => {\n  assertUniqueId(\"about-page\");\n  route(\"about\", \"routes/page.tsx\", { id: \"about-page\" });\n  assertUniqueId(\"company-page\");\n  route(\"company\", \"routes/page.tsx\", { id: \"company-page\" });\n});","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give every route a unique file, or explicit unique ids when reusing a file","When generating routes from data, key by a unique field and assert uniqueness","Search the definitions for a repeated file path before reporting the bug"],"tags":["routes-config","duplicate","route-id","define-routes"],"backgroundTag":"duplicate-route-id","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"}