clockworklabs/SpacetimeDB · error · ArgumentException

Route paths must start with `/`: {path}

Error message

Route paths must start with `/`: {path}

What it means

AssertValidPath requires every route path (including Nest prefixes) to be either empty or begin with '/'. A non-empty path whose first character is not '/' throws ArgumentException with the offending path embedded.

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 524b4487d9)

Solutions

  1. Add the leading slash: "/users" instead of "users"
  2. Normalize config-driven paths through a helper that prefixes '/' when missing
  3. Unit-test route construction at startup so bad config fails fast with a clear location

Example fix

// before
var router = Router.New().Get(config.UsersPath, listUsers); // UsersPath = "users"

// after
static string Route(string p) => p.Length > 0 && p[0] != '/' ? "/" + p : p;
var router = Router.New().Get(Route(config.UsersPath), listUsers);
Defensive patterns

Strategy: validation

Validate before calling

static string NormalizeRoutePath(string p) =>
    string.IsNullOrEmpty(p) ? p : (p[0] == '/' ? p : "/" + p);

Type guard

static bool HasLeadingSlash(string path) => path.Length == 0 || path[0] == '/';

Try / catch

try { router = router.Get(path, handler); }
catch (ArgumentException e) when (e.Message.Contains("must start with `/`"))
{ /* normalize the config-derived path and retry registration */ }

Prevention

When it happens

Trigger: Passing "users", "api/users", or a config-derived value that lost its leading slash to Get/Post/Put/Delete/Patch/Head/Options/Any/Nest/Merge.

Common situations: Route tables loaded from JSON/env config where the slash was trimmed; interpolating segment variables like $"{base}/users" with base = "" ; porting code from frameworks that accept slash-less paths.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/09c1d4e29f1258cc. Report an issue: GitHub.