{"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":"exception","errorClass":"Error","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/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-remix-routes-option-adapter/defineRoutes.ts#L85-L121","documentation":"Thrown by `defineRoutes()` from `@react-router/remix-routes-option-adapter` when two calls produce a route with the same `id`. The id is `options.id` if provided, otherwise derived from the `file` argument via `createRouteId(file)` (slashes normalized, file extension stripped). The manifest is keyed by id, so collisions make the structure ambiguous.","triggerScenarios":"Two `defineRoute(path, file, ...)` calls with the same `file` string (e.g. `routes/parent` and `routes/parent.tsx` both collapse to id `routes/parent`), or two routes that pass the same explicit `options.id`. Also triggered by case-only or slash-only differences in `file` after normalization.","commonSituations":"Migrating from Remix's `defineRoutes` config and accidentally pointing two routes at one module; copy-pasting a route block and forgetting to change the file path; mixing manual `id` overrides that collide; Windows backslash paths colliding with POSIX forward-slash paths after `normalizeSlashes`.","solutions":["Inspect the printed id and grep `defineRoute(` calls for any other call producing the same id.","Give each colliding route a distinct `file`, or pass an explicit unique `options.id` for routes that intentionally share a file.","If two routes legitimately need one module, define the module once and reference it from a single parent with child routes.","Run `normalizeSlashes` mentally on each `file` argument to confirm they don't collapse to the same id."],"exampleFix":"// before\ndefineRoutes((route) => {\n  route('foo', 'routes/foo.tsx');\n  route('foo/bar', 'routes/foo.tsx', () => {}); // duplicate id 'routes/foo'\n});\n\n// after\ndefineRoutes((route) => {\n  route('foo', 'routes/foo.tsx', () => {\n    route('foo/bar', 'routes/foo/bar.tsx');\n  });\n});","handlingStrategy":"validation","validationCode":"// Before calling defineRoutes, assert unique ids\nimport { normalizeSlashes } from '@react-router/remix-routes-option-adapter/normalizeSlashes';\nfunction stripExt(file: string) { return file.replace(/\\.[a-z0-9]+$/i, ''); }\nfunction assertUniqueRouteIds(calls: Array<{ file: string; id?: string }>) {\n  const seen = new Set<string>();\n  for (const c of calls) {\n    const id = c.id ?? normalizeSlashes(stripExt(c.file));\n    if (seen.has(id)) throw new Error(`Duplicate route id: ${id}`);\n    seen.add(id);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep a single source of truth for route files and let file paths drive ids.","Never reuse an explicit `id` across routes.","Add a unit test that runs your defineRoutes callback and asserts the manifest has N unique ids."],"tags":["routing","config","define-routes","duplicate-id"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}