clockworklabs/SpacetimeDB · error · TypeError

Cannot nest router at `${path}`; existing routes overlap wit

Error message

Cannot nest router at `${path}`; existing routes overlap with nested path

What it means

Router.nest(path, subRouter) mounts a sub-router's routes under path. Before merging, it checks that no already-registered route path starts with the nest path, because the merged sub-routes would collide with those existing routes. If any current route has the nest path as a prefix, nest throws a TypeError.

Source

Thrown at crates/bindings-typescript/src/server/http_handlers.ts:320

    );
  }

  patch(path: string, handler: HttpHandlerExport<any>) {
    return this.addRoute(
      { tag: 'Method', value: { tag: 'Patch' } },
      path,
      handler
    );
  }

  any(path: string, handler: HttpHandlerExport<any>) {
    return this.addRoute({ tag: 'Any' }, path, handler);
  }

  nest(path: string, subRouter: Router) {
    assertValidPath(path);
    if (this.#routes.some(route => route.path.startsWith(path))) {
      throw new TypeError(
        `Cannot nest router at \`${path}\`; existing routes overlap with nested path`
      );
    }
    let merged = new Router(this.#routes);
    for (const route of subRouter.#routes) {
      merged = merged.addRoute(
        route.method,
        joinPaths(path, route.path),
        route.handler
      );
    }
    return merged;
  }

  merge(otherRouter: Router) {
    let merged = new Router(this.#routes);
    for (const route of otherRouter.#routes) {
      merged = merged.addRoute(route.method, route.path, route.handler);

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Move the conflicting parent routes into the sub-router (or delete them) before nesting
  2. Nest first, then register any parent-level routes that do not share the prefix
  3. Choose a nest path that is not a prefix of any existing route, e.g. nest('/v2/api', sub) instead of '/api'

Example fix

// before
const router = new Router()
  .get('/api/users', listUsers)
  .nest('/api', apiSubRouter); // throws: '/api/users' starts with '/api'

// after: overlapping routes live in the sub-router
const apiSubRouter = new Router().get('/users', listUsers);
const router = new Router().nest('/api', apiSubRouter);
Defensive patterns

Strategy: validation

Validate before calling

function canNest(router: Router, path: string): boolean {
  return !router.intoRoutes().some(r => r.path.startsWith(path));
}
// before mounting:
if (!canNest(router, '/api')) throw new Error('nest would overlap existing routes');

Prevention

When it happens

Trigger: Calling router.get('/api/users', h) first and then router.nest('/api', subRouter): '/api/users'.startsWith('/api') is true, so nesting is refused. Also nest('', sub) conflicts with every route once any route exists.

Common situations: Refactoring a flat router into nested sub-routers while some old routes remain in the parent; copy-pasting setup code that registers a route under the same prefix being mounted; mounting at the root path '' after registering anything.

Related errors


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