{"record":{"id":"75167f17ead91651","repo":"clockworklabs/SpacetimeDB","slug":"route-paths-may-contain-only-acceptableroutepathc","errorCode":null,"errorMessage":"Route paths may contain only {AcceptableRoutePathCharsHumanDescription}: {path}","messagePattern":"Route paths may contain only (.+?): (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"crates/bindings-csharp/Runtime/Router.cs","lineNumber":154,"sourceCode":"        }\n\n        return a.Method is MethodOrAny.Any\n            || b.Method is MethodOrAny.Any\n            || Equals(a.Method, b.Method);\n    }\n\n    private static void AssertValidPath(string path)\n    {\n        ArgumentNullException.ThrowIfNull(path);\n        if (path.Length > 0 && path[0] != '/')\n        {\n            throw new ArgumentException($\"Route paths must start with `/`: {path}\", nameof(path));\n        }\n        foreach (var c in path)\n        {\n            if (!CharacterIsAcceptableForRoutePath(c))\n            {\n                throw new ArgumentException(\n                    $\"Route paths may contain only {AcceptableRoutePathCharsHumanDescription}: {path}\",\n                    nameof(path)\n                );\n            }\n        }\n    }\n\n    private static bool CharacterIsAcceptableForRoutePath(char c) =>\n        c is (>= 'a' and <= 'z') or (>= '0' and <= '9') or '-' or '_' or '~' or '/';\n}\n","sourceCodeStart":136,"sourceCodeEnd":165,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-csharp/Runtime/Router.cs#L136-L165","documentation":"Route paths accept only ASCII lowercase letters, digits, '-', '_', '~' and '/'. AssertValidPath scans every character and throws ArgumentException listing the allowed set. Notably rejected: uppercase letters, dots, colons, and braces — this router has no path-parameter syntax, so '/users/{id}'-style paths from other frameworks are invalid here.","triggerScenarios":"Registering \"/Users\" (uppercase), \"/v1.0/users\" (dot), \"/users/{id}\" or \"/users/:id\" (parameter placeholders), or any path containing uppercase/non-ASCII characters.","commonSituations":"Porting route tables from Express/ASP.NET-style routers that support parameters; versioned paths with dots; case-mismatched copies of paths.","solutions":["Lowercase the whole path and strip unsupported characters","Remove path-parameter placeholders — this router matches static paths only; encode the variable part in the handler or a query string instead","Rewrite versioned paths like '/v1.0/users' as '/v1_0/users'"],"exampleFix":"// before\nvar router = Router.New().Get(\"/users/{id}\", getUser); // '{', '}' rejected\n\n// after\nvar router = Router.New().Get(\"/users\", listUsers); // static paths only;\n// read selection criteria from the request inside the handler","handlingStrategy":"validation","validationCode":"static bool IsValidRoutePath(string path) =>\n    (path.Length == 0 || path[0] == '/')\n    && path.All(c => c is (>= 'a' and <= 'z') or (>= '0' and <= '9') or '-' or '_' or '~' or '/');","typeGuard":null,"tryCatchPattern":"try { router = router.Get(path, handler); }\ncatch (ArgumentException e) when (e.Message.Contains(\"may contain only\"))\n{ /* lowercase the path, drop dots/placeholders, then retry */ }","preventionTips":["Remember this router has no path parameters — design static paths only","Validate route tables from config with the same character predicate the Router uses"],"tags":["routing","path-validation","csharp"],"backgroundTag":"invalid-characters-in-route-path","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}