{"record":{"id":"66b4647ef728ae88","repo":"vercel/next.js","slug":"each-route-must-start-with-route","errorCode":null,"errorMessage":"Each route must start with '/': ${route}","messagePattern":"Each route must start with '/': (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"bench/render-pipeline/benchmark.ts","lineNumber":141,"sourceCode":"      '/streaming/heavy',\n      '/streaming/chunkstorm',\n      '/streaming/wide',\n      '/streaming/bulk',\n    ]\n  }\n\n  const routes = rawRoutes\n    .split(',')\n    .map((route) => route.trim())\n    .filter(Boolean)\n\n  if (routes.length === 0) {\n    throw new Error('--routes cannot be empty')\n  }\n\n  for (const route of routes) {\n    if (!route.startsWith('/')) {\n      throw new Error(`Each route must start with '/': ${route}`)\n    }\n  }\n\n  return routes\n}\n\nfunction usage() {\n  console.log(`Usage: pnpm bench:render-pipeline [options]\n\nOptions:\n  --scenario=e2e|minimal-server                  (default: e2e)\n    e2e:            Real production server (next build + next start).\n    minimal-server: NextServer with minimalMode, no router-server.\n  --json-out=<path>\n\nBenchmark options:\n  --app-dir=<path>                              (default: bench/basic-app)\n  --routes=/,/streaming/light,...               (default: built-in stress suite)","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/bench/render-pipeline/benchmark.ts#L123-L159","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Prefix every route with '/', e.g. --routes=/dashboard,/streaming/light.","If you meant to benchmark the root, use '/' (not empty string).","Do not include scheme/host; pass only the path portion.","Re-check after comma-splitting that no entry lost its slash."],"exampleFix":"# before\n#   pnpm bench:render-pipeline --routes=dashboard,/blog\n\n# after\n#   pnpm bench:render-pipeline --routes=/dashboard,/blog","handlingStrategy":"validation","validationCode":"function normalizeRoute(route: string): string {\n  const trimmed = route.trim()\n  if (!trimmed.startsWith('/')) throw new Error(`route must start with '/': ${route}`)\n  return trimmed\n}\n// apply to every entry before passing to parseRoutes","typeGuard":"function isAbsolutePathRoute(route: string): boolean {\n  return route.startsWith('/')\n}","tryCatchPattern":"try {\n  const routes = parseRoutes(args.get('routes'))\n} catch (err) {\n  if (/must start with '\\/' .test((err as Error).message)) {\n    console.error('Each route must be an absolute path (start with /). Got:', (err as Error).message)\n    process.exit(2)\n  }\n  throw err\n}","preventionTips":["Prefix every route with '/'; the root is '/', not empty.","Pass only the path portion, never scheme/host.","Double-check entries after comma-splitting.","If sourcing routes from a config, normalize them at the source."],"tags":["cli","argument-parsing","routes","validation","url","render-pipeline"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}