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

  1. Prefix the path with '/': "/users"
  2. If paths come from configuration, normalize them at load time: path.StartsWith('/') ? path : "/" + path
  3. 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

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


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)