clockworklabs/SpacetimeDB · critical

Router registration failed: %s

Error message

Router registration failed: %s

What it means

The HTTP Router (unstable feature, requires SPACETIMEDB_UNSTABLE_FEATURES) validates every route path at registration time. fail_router_registration prints the specific reason and calls std::abort(), so the process dies during static initialization — before main. Reasons include: a path not starting with '/', a character outside [a-z0-9-_~/] (uppercase and spaces are rejected), nest() into a prefix that existing routes already use, and duplicate method+path pairs.

Source

Thrown at crates/bindings-cpp/include/spacetimedb/router.h:99

    }

    Router merge(const Router& other) const {
        Router merged = *this;
        for (const auto& route : other.routes_) {
            merged = merged.add_route(route.method, route.path, route.handler_name);
        }
        return merged;
    }

    const std::vector<RouteSpec>& routes() const {
        return routes_;
    }

private:
    std::vector<RouteSpec> routes_;

    [[noreturn]] static void fail_router_registration(const std::string& message) {
        std::fprintf(stderr, "Router registration failed: %s\n", message.c_str());
        std::abort();
    }

    static bool character_is_acceptable_for_route_path(char c) {
        return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '~' || c == '/';
    }

    static void assert_valid_path(const std::string& path) {
        if (!path.empty() && path[0] != '/') {
            fail_router_registration("Route paths must start with `/`: " + path);
        }
        for (char c : path) {
            if (!character_is_acceptable_for_route_path(c)) {
                fail_router_registration("Route paths may contain only ASCII lowercase letters, digits and `-_~/`: " + path);
            }
        }
    }

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Read the message text after 'Router registration failed:' — it names the exact rule and offending path
  2. Normalize paths: start with '/', lowercase only, restricted to a-z 0-9 - _ ~ /
  3. For nest() collisions, restructure prefixes so no existing route starts with the nest path, or nest before adding overlapping routes
  4. For duplicates found via routes_overlap, remove or rename one of the same method+path registrations
  5. Re-run: abort happens at static init, so the module process must simply start cleanly

Example fix

// before — aborts at startup
auto r = SpacetimeDB::Router{}.get("Users", h)          // no leading '/', uppercase
                         .get("/users/:id", h2);       // ':' not allowed
// after
auto r = SpacetimeDB::Router{}.get("/users", h)
                         .get("/users/~id", h2);      // valid charset, leading '/'
Defensive patterns

Strategy: validation

Validate before calling

// Validate before building the Router (abort() cannot be caught):
#include <cctype>
bool RoutePathIsValid(const std::string& p) {
    if (p.empty() || p[0] != '/') return false;
    for (char c : p) {
        bool ok = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')
                  || c == '-' || c == '_' || c == '~' || c == '/';
        if (!ok) return false;
    }
    return true;
}
// assert RoutePathIsValid(path) for every route in a unit test / startup check

Prevention

When it happens

Trigger: Calling Router::get("users", h) without a leading slash; paths containing uppercase, spaces, dots, or other characters rejected by character_is_acceptable_for_route_path; Router::nest("/api", sub) when routes already beginning with /api exist; merging two routers that both define the same method and path (routes_overlap).

Common situations: Porting REST paths verbatim from another framework that allowed case-insensitive or parameterized paths like '/users/:id' (':' is rejected); composing routers with nest() where prefixes collide; refactoring a route from one method to another while forgetting the old registration; enabling the unstable HTTP feature for the first time on legacy path strings.

Related errors


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