clockworklabs/SpacetimeDB · error
Route conflict for `{path}`
Error message
Route conflict for `{path}` What it means
add_route panics when a candidate route overlaps an existing one: the paths are identical AND either handler uses Method::Any or both use the same method. Registering different methods on the same path is legal; this panic means a true duplicate or an Any collision.
Source
Thrown at crates/bindings/src/http.rs:387
}
pub(crate) fn into_routes(self) -> Vec<RouteSpec> {
self.routes
}
fn add_route(mut self, method: MethodOrAny, path: impl Into<String>, handler: Handler) -> Self {
let path = path.into();
assert_valid_path(&path);
let candidate = RouteSpec {
method: method.clone(),
path: path.clone(),
handler,
};
// TODO(perf): Adding a route is O(n), which means that building a router is O(n^2)
if self.routes.iter().any(|route| routes_overlap(route, &candidate)) {
panic!("Route conflict for `{path}`");
}
self.routes.push(candidate);
self
}
}
#[cfg(feature = "unstable")]
fn join_paths(prefix: &str, suffix: &str) -> String {
if prefix == "/" {
return suffix.to_string();
}
if suffix == "/" {
return prefix.to_string();
}
let prefix = prefix.trim_end_matches('/');
let suffix = suffix.trim_start_matches('/');
format!("{prefix}/{suffix}")View on GitHub (pinned to 6dee26c6ef)
Solutions
- Delete or rename the duplicate registration - search for the path shown in the panic message.
- If a catch-all is intended, keep a single Method::Any handler per path and remove per-method handlers there.
- When merging routers, de-duplicate shared paths before merging.
Example fix
// before
let r = Router::new()
.route(Method::GET, "/users", list)
.route(Method::GET, "/users", list_again) // panics
.route(Method::POST, "/users", create); // ok: different method
// after
let r = Router::new()
.route(Method::GET, "/users", list)
.route(Method::POST, "/users", create); Defensive patterns
Strategy: validation
Validate before calling
use std::collections::HashSet;
let mut seen: HashSet<(Method, String)> = HashSet::new();
let key = (method.clone(), path.to_string());
assert!(!seen.contains(&(MethodOrAny::Any, path.to_string())) && !seen.contains(&key), "duplicate route {path}");
seen.insert(key); Prevention
- Register each path+method exactly once; keep route registration in a single table or builder.
- Remember Method::Any collides with every specific method on the same path.
- When merging routers, de-duplicate shared paths first.
When it happens
Trigger: Two .route(Method::GET, "/users", ...) registrations (often from merged routers); .route(Method::Any, "/users", ...) after a specific-method route on "/users"; nest() merging a sub-router that contains a path already added on the parent.
Common situations: Combining Router::merge outputs from multiple modules; copy-pasted route blocks; registering fallback Any handlers alongside per-method handlers.
Related errors
- Cannot nest router at `{path}`; existing routes overlap with
- Cannot nest router at `{path}`; existing routes overlap with
- Route conflict for `{path}`
- Route paths must start with `/`: {path}
- Route paths may contain only {}: {path}
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/874ed4d3d50b5234.
Report an issue: GitHub.