{"record":{"id":"2d3941552ab5fef3","repo":"clockworklabs/SpacetimeDB","slug":"route-paths-must-start-with-path-2d3941","errorCode":null,"errorMessage":"Route paths must start with `/`: {path}","messagePattern":"Route paths must start with `/`: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bindings/src/http.rs","lineNumber":411,"sourceCode":"}\n\n#[cfg(feature = \"unstable\")]\nfn join_paths(prefix: &str, suffix: &str) -> String {\n    if prefix == \"/\" {\n        return suffix.to_string();\n    }\n    if suffix == \"/\" {\n        return prefix.to_string();\n    }\n    let prefix = prefix.trim_end_matches('/');\n    let suffix = suffix.trim_start_matches('/');\n    format!(\"{prefix}/{suffix}\")\n}\n\n#[cfg(feature = \"unstable\")]\nfn assert_valid_path(path: &str) {\n    if !path.is_empty() && !path.starts_with('/') {\n        panic!(\"Route paths must start with `/`: {path}\");\n    }\n    if !path.chars().all(character_is_acceptable_for_route_path) {\n        panic!(\n            \"Route paths may contain only {}: {path}\",\n            ACCEPTABLE_ROUTE_PATH_CHARS_HUMAN_DESCRIPTION\n        );\n    }\n}\n\n#[cfg(feature = \"unstable\")]\nfn routes_overlap(a: &RouteSpec, b: &RouteSpec) -> bool {\n    if a.path != b.path {\n        return false;\n    }\n    matches!(a.method, MethodOrAny::Any) || matches!(b.method, MethodOrAny::Any) || a.method == b.method\n}\n\n/// Allows performing HTTP requests via [`HttpClient::send`] and [`HttpClient::get`].","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings/src/http.rs#L393-L429","documentation":"assert_valid_path rejects any non-empty route path that does not begin with '/'. Router construction methods (route, nest) validate every path string, so a missing leading slash panics immediately at router-build time rather than failing at request matching.","triggerScenarios":"Passing \"users\" instead of \"/users\" to .route(...) or .nest(...); building paths dynamically with format! or env vars that omit the leading slash; joining an empty prefix incorrectly so the slash is lost.","commonSituations":"Porting handlers from frameworks where paths are relative (actix-style \"/x\" vs template-relative strings); config-driven route registration where the config file omits the slash.","solutions":["Add the leading slash to the path in the panic message.","If paths come from config or format!, normalize them with a helper that prepends '/' when missing.","Use join_paths-style construction (prefix ends with '/', suffix starts with '/') when composing paths."],"exampleFix":"// before\nlet r = Router::new().route(Method::GET, \"users\", list); // panics\n\n// after\nlet r = Router::new().route(Method::GET, \"/users\", list);","handlingStrategy":"validation","validationCode":"fn normalize_route_path(p: &str) -> String {\n    if p.starts_with('/') { p.to_string() } else { format!(\"/{p}\") }\n}\nassert!(normalize_route_path(\"/users\").starts_with('/'));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write route paths with a leading '/' in source.","Normalize config-sourced or dynamically built paths before registering them."],"tags":["rust","http","router","path-validation"],"backgroundTag":"invalid-route-path","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"}