{"record":{"id":"8092cef0d8d3574f","repo":"angular/angular-cli","slug":"invalid-topath-the-string-must-start-with-a","errorCode":null,"errorMessage":"Invalid toPath: The string must start with a '/'. Received: '${toPath}'","messagePattern":"Invalid toPath: The string must start with a '/'\\. Received: '(.+?)'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/angular/ssr/src/utils/url.ts","lineNumber":186,"sourceCode":" * @returns A resolved path string with `*` placeholders replaced by segments from the `fromPath`,\n * or the `toPath` returned unchanged if it contains no placeholders.\n *\n * @throws If the `toPath` does not start with a `/`, indicating an invalid path format.\n *\n * @example\n * ```typescript\n * // Example with placeholders resolved\n * const resolvedPath = buildPathWithParams('/*\\/details', '/123/abc');\n * console.log(resolvedPath); // Outputs: '/123/details'\n *\n * // Example with a static path\n * const staticPath = buildPathWithParams('/static/path', '/base/unused');\n * console.log(staticPath); // Outputs: '/static/path'\n * ```\n */\nexport function buildPathWithParams(toPath: string, fromPath: string): string {\n  if (toPath[0] !== '/') {\n    throw new Error(`Invalid toPath: The string must start with a '/'. Received: '${toPath}'`);\n  }\n\n  if (fromPath[0] !== '/') {\n    throw new Error(`Invalid fromPath: The string must start with a '/'. Received: '${fromPath}'`);\n  }\n\n  if (!toPath.includes('/*')) {\n    return toPath;\n  }\n\n  const fromPathParts = fromPath.split('/');\n  const toPathParts = toPath.split('/');\n  const resolvedParts = toPathParts.map((part, index) =>\n    toPathParts[index] === '*' ? fromPathParts[index] : part,\n  );\n\n  return joinUrlParts(...resolvedParts);\n}","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/ssr/src/utils/url.ts#L168-L204","documentation":"buildPathWithParams in @angular/ssr merges route parameters from a source path into a destination ('to') path. Both arguments must be root-relative absolute paths. It throws when the destination path (toPath) does not start with '/', because relative destinations cannot be deterministically resolved against the base.","triggerScenarios":"Calling buildPathWithParams('static/path', '/base') or any toPath lacking a leading slash (empty string, 'foo/bar', './foo') from handle/result flows.","commonSituations":"Joining path segments with string concatenation instead of a path utility so the leading slash is lost; stripping the slash with regex trims; reading a route path from config that was authored as relative; passing an empty string when a route is missing.","solutions":["Prefix the destination with '/': buildPathWithParams('/' + toPath.replace(/^\\/+/, ''), fromPath).","Verify the value passed as toPath is the configured route path, not a relative file path or empty string.","If paths come from user/config input, validate with toPath.startsWith('/') before calling."],"exampleFix":"// before\nbuildPathWithParams(route.template, '/base');\n// after\nconst toPath = route.template.startsWith('/') ? route.template : '/' + route.template;\nbuildPathWithParams(toPath, '/base');","handlingStrategy":"validation","validationCode":"function isValidToPath(p: unknown): p is string {\n  return typeof p === 'string' && p.startsWith('/');\n}\nif (!isValidToPath(toPath)) throw new TypeError(`toPath must be absolute: got '${toPath}'`);","typeGuard":"function isAbsolutePath(p: unknown): p is string {\n  return typeof p === 'string' && p.startsWith('/');\n}","tryCatchPattern":"try {\n  const staticPath = buildPathWithParams(toPath, fromPath);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Invalid toPath:')) {\n    // fall back to normalized path\n  } else throw e;\n}","preventionTips":["Always build destination paths from root-relative route templates that begin with '/'.","Normalize user/config-supplied paths with a helper that guarantees a leading slash before calling.","Guard against empty strings when a route lookup can miss."],"tags":["angular","ssr","path-validation","argument-error"],"backgroundTag":"path-must-be-absolute","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}