clockworklabs/SpacetimeDB · error · ArgumentException
Route paths must start with `/
Error message
Route paths must start with `/`: {path} What it means
AssertValidPath runs on every route registration (Get/Post/.../Any/Nest) and requires the path to be null-checked and, when non-empty, to begin with '/'. A path missing the leading slash — e.g. "users" instead of "/users" — is rejected immediately with this ArgumentException (param name 'path'). The empty string "" is the one allowed slash-less value.
Solutions
- Prefix the path with '/': "/users"
- If paths come from configuration, normalize them at load time: path.StartsWith('/') ? path : "/" + path
- Keep route constants in one place and lint them for the leading slash
Example fix
// before
router.Get("users", listUsers); // throws: Route paths must start with `/`
// after
router.Get("/users", listUsers); Defensive patterns
Strategy: validation
Validate before calling
// Normalize before registering:
static string NormalizeRoutePath(string p) =>
string.IsNullOrEmpty(p) ? "/" : (p.StartsWith('/') ? p : "/" + p); Prevention
- Keep all route strings as constants starting with '/'
- Normalize externally sourced paths (config/DB) once at load time
- Write a unit test that asserts every registered path matches ^/
When it happens
Trigger: router.Get("users", h), router.Nest("v1", sub), or building paths with string concatenation that drops the leading '/'; passing a path variable configured without the initial slash.
Common situations: Porting routes from frameworks that accept slash-less paths (Express/Koa style); assembling paths from config or constants where the '/' got trimmed; typos in route tables.
Related errors
- Route paths may contain only
- Cannot nest router at
- Route conflict for
- Route paths may contain only
- Route paths must start with `/
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/09c1d4e29f1258cc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/bindings-csharp/Runtime/Router.cs:148
private static bool RoutesOverlap(RouteSpec a, RouteSpec b)
{
if (!string.Equals(a.Path, b.Path, StringComparison.Ordinal))
{
return false;
}
return a.Method is MethodOrAny.Any
|| b.Method is MethodOrAny.Any
|| Equals(a.Method, b.Method);
}
private static void AssertValidPath(string path)
{
ArgumentNullException.ThrowIfNull(path);
if (path.Length > 0 && path[0] != '/')
{
throw new ArgumentException($"Route paths must start with `/`: {path}", nameof(path));
}
foreach (var c in path)
{
if (!CharacterIsAcceptableForRoutePath(c))
{
throw new ArgumentException(
$"Route paths may contain only {AcceptableRoutePathCharsHumanDescription}: {path}",
nameof(path)
);
}
}
}
private static bool CharacterIsAcceptableForRoutePath(char c) =>
c is (>= 'a' and <= 'z') or (>= '0' and <= '9') or '-' or '_' or '~' or '/';
}
View on GitHub (pinned to 6dee26c6ef)