vercel/next.js · error

Each route must start with '/': ${route}

Error message

Each route must start with '/': ${route}

What it means

Thrown by parseRoutes (benchmark.ts:141) when a route in the --routes list does not start with '/'. The benchmark builds URLs as http://127.0.0.1:{port}{route}, so a route without a leading slash would either be a relative URL (resolving against the base incorrectly) or produce a malformed path. The check enforces the absolute-path convention before any request is made.

Source

Thrown at bench/render-pipeline/benchmark.ts:141

      '/streaming/heavy',
      '/streaming/chunkstorm',
      '/streaming/wide',
      '/streaming/bulk',
    ]
  }

  const routes = rawRoutes
    .split(',')
    .map((route) => route.trim())
    .filter(Boolean)

  if (routes.length === 0) {
    throw new Error('--routes cannot be empty')
  }

  for (const route of routes) {
    if (!route.startsWith('/')) {
      throw new Error(`Each route must start with '/': ${route}`)
    }
  }

  return routes
}

function usage() {
  console.log(`Usage: pnpm bench:render-pipeline [options]

Options:
  --scenario=e2e|minimal-server                  (default: e2e)
    e2e:            Real production server (next build + next start).
    minimal-server: NextServer with minimalMode, no router-server.
  --json-out=<path>

Benchmark options:
  --app-dir=<path>                              (default: bench/basic-app)
  --routes=/,/streaming/light,...               (default: built-in stress suite)

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Prefix every route with '/', e.g. --routes=/dashboard,/streaming/light.
  2. If you meant to benchmark the root, use '/' (not empty string).
  3. Do not include scheme/host; pass only the path portion.
  4. Re-check after comma-splitting that no entry lost its slash.

Example fix

# before
#   pnpm bench:render-pipeline --routes=dashboard,/blog

# after
#   pnpm bench:render-pipeline --routes=/dashboard,/blog
Defensive patterns

Strategy: validation

Validate before calling

function normalizeRoute(route: string): string {
  const trimmed = route.trim()
  if (!trimmed.startsWith('/')) throw new Error(`route must start with '/': ${route}`)
  return trimmed
}
// apply to every entry before passing to parseRoutes

Type guard

function isAbsolutePathRoute(route: string): boolean {
  return route.startsWith('/')
}

Try / catch

try {
  const routes = parseRoutes(args.get('routes'))
} catch (err) {
  if (/must start with '\/' .test((err as Error).message)) {
    console.error('Each route must be an absolute path (start with /). Got:', (err as Error).message)
    process.exit(2)
  }
  throw err
}

Prevention

When it happens

Trigger: Passing --routes=dashboard (missing slash), --routes=/streaming/light,dashboard (one bad entry), or routes with a hostname like http://host/x. Each entry is checked individually so one bad route aborts the whole list.

Common situations: Typing routes without the leading slash; pasting route names from a config that omits the slash; mixing in a full URL where a path was expected.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/66b4647ef728ae88. Report an issue: GitHub.