clockworklabs/SpacetimeDB · error · TypeError

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

Error message

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

What it means

Server modules register HTTP routes through Router (router.get/post/put/.../any and router.nest). assertValidPath requires every route path to be either '' (the module root) or begin with '/', since paths are matched literally by the HTTP dispatch layer. A path missing the leading slash is a programmer error and throws a TypeError at module build time.

Source

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

    return body;
  }
  return textDecoder.decode(body);
}

function characterIsAcceptableForRoutePath(c: string) {
  return (
    (c >= 'a' && c <= 'z') ||
    (c >= '0' && c <= '9') ||
    c === '-' ||
    c === '_' ||
    c === '~' ||
    c === '/'
  );
}

function assertValidPath(path: string) {
  if (path !== '' && !path.startsWith('/')) {
    throw new TypeError(`Route paths must start with \`/\`: ${path}`);
  }
  if (![...path].every(characterIsAcceptableForRoutePath)) {
    throw new TypeError(
      `Route paths may contain only ${ACCEPTABLE_ROUTE_PATH_CHARS_HUMAN_DESCRIPTION}: ${path}`
    );
  }
}

function routesOverlap(a: RouteSpec, b: RouteSpec) {
  const methodsMatch = (left: HttpMethod, right: HttpMethod) => {
    if (left.tag !== right.tag) {
      return false;
    }
    if (left.tag === 'Extension' && right.tag === 'Extension') {
      return left.value === right.value;
    }
    return true;
  };

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Prepend '/' to the offending path: 'health' becomes '/health'
  2. If the path is computed, normalize it: const p = raw === '' || raw.startsWith('/') ? raw : '/' + raw
  3. Run module tests so route registration executes before deploy; this throws during build, never at request time

Example fix

// before
router.get('health', handler);

// after
router.get('/health', handler);
Defensive patterns

Strategy: validation

Validate before calling

function assertRoutePathStart(path: string): void {
  if (path !== '' && !path.startsWith('/')) {
    throw new TypeError(`Route paths must start with \`/\`: ${path}`);
  }
}
// call on every path before router.get/post/...

Type guard

const hasLeadingSlash = (p: string): p is `/${string}` | '' =>
  p === '' || p.startsWith('/');

Prevention

When it happens

Trigger: Registering a route with a relative path such as router.get('health', handler) or router.any('api/users', handler); '' is the only permitted value that does not start with '/'.

Common situations: Porting handlers from Express-style code where 'users' is tolerated; building paths dynamically (base + '/users') and forgetting the slash on the first segment; simple typos.

Related errors


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