{"record":{"id":"c72489b0903f6ef0","repo":"clockworklabs/SpacetimeDB","slug":"cannot-nest-router-at-path-existing-routes-ov-c72489","errorCode":null,"errorMessage":"Cannot nest router at `{path}`; existing routes overlap with nested path","messagePattern":"Cannot nest router at `(.+?)`; existing routes overlap with nested path","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings/src/http.rs","lineNumber":349,"sourceCode":"        self.add_route(MethodOrAny::Any, path, handler)\n    }\n\n    /// Causes requests which start with `path` to be processed by `sub_router`.\n    ///\n    /// `sub_router` will be used by stripping the leading `path` from the path of the request.\n    ///\n    /// Panics if `self` already has any handlers registered on paths which start with `path`.\n    ///\n    /// Panics if the `path` is [invalid](Self#paths).\n    pub fn nest(self, path: impl Into<String>, sub_router: Self) -> Self {\n        let path = path.into();\n        assert_valid_path(&path);\n\n        // FIXME: either this check is too restrictive, or the checks in the other methods are too lenient.\n        // Do we want it to be the case that the `sub_router` effectively takes ownership of the whole route below `path`,\n        // or just the routes it actually contains?\n        if self.routes.iter().any(|route| route.path.starts_with(&path)) {\n            panic!(\"Cannot nest router at `{path}`; existing routes overlap with nested path\");\n        }\n\n        let mut merged = self;\n        for route in sub_router.routes {\n            let nested_path = join_paths(&path, &route.path);\n            merged = merged.add_route(route.method, nested_path, route.handler);\n        }\n        merged\n    }\n\n    /// Combines all of the routes in `self` and `other_router` into a single [`Router`].\n    ///\n    /// Panics if any of the routes in `self` conflict with any of the routes in `other_router`.\n    pub fn merge(self, other_router: Self) -> Self {\n        let mut merged = self;\n        for route in other_router.routes {\n            merged = merged.add_route(route.method, route.path, route.handler);\n        }","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings/src/http.rs#L331-L367","documentation":"Router::nest panics when the parent router already has any handler whose path starts with the nest prefix, because merging the sub-router would produce two handlers under the same subtree. The check is deliberately strict (see the FIXME in the source): even non-conflicting sub-paths trigger it.","triggerScenarios":"Registering a route under the prefix before nesting, e.g. router.route(GET, \"/api/health\", h) followed by router.nest(\"/api\", sub_router); nesting two sub-routers at overlapping prefixes such as \"/api\" then \"/api/v2\".","commonSituations":"Composing routers in library crates where each crate registers a few routes and one also nests; refactoring flat routes into nested sub-routers incrementally.","solutions":["Nest first: call nest(\"/api\", sub) before adding any top-level routes under /api.","Move the offending parent route into the sub-router (sub.route(GET, \"/health\", h)) so the whole subtree has one owner.","Nest at a prefix that does not prefix-match any existing route path."],"exampleFix":"// before\nlet r = Router::new()\n    .route(Method::GET, \"/api/health\", health)\n    .nest(\"/api\", api_router); // panics: /api/health starts with /api\n\n// after: subtree owned entirely by the nested router\nlet api_router = api_router.route(Method::GET, \"/health\", health);\nlet r = Router::new().nest(\"/api\", api_router);","handlingStrategy":"validation","validationCode":"let prefix = \"/api\";\nlet taken: Vec<String> = vec![\"/api/health\".into()]; // your registry of registered paths\nassert!(!taken.iter().any(|p| p.starts_with(prefix)), \"cannot nest at {prefix}\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Nest sub-routers before registering any routes under their prefix.","Give each subtree exactly one owner: routes under /x live only in the router nested at /x.","Centralize router construction in one function so ordering is reviewable."],"tags":["rust","http","router","route-conflict","nesting"],"backgroundTag":"route-conflict","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}