{"record":{"id":"3a17fefc580f909e","repo":"angular/angular-cli","slug":"the-getprerenderparams-function-defined-for-the","errorCode":null,"errorMessage":"The 'getPrerenderParams' function defined for the '${stripLeadingSlash(currentRoutePath)}' route returned a non-string value for parameter '${parameterName}'. Please make sure the 'getPrerenderParams' function returns values for all parameters specified in this route.","messagePattern":"The 'getPrerenderParams' function defined for the '(.+?)' route returned a non-string value for parameter '(.+?)'\\. Please make sure the 'getPrerenderParams' function returns values for all parameters specified in this route\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/angular/ssr/src/routes/ng-routes.ts","lineNumber":520,"sourceCode":"}\n\n/**\n * Creates a replacer function used for substituting parameter placeholders in a route path\n * with their corresponding values provided in the `params` object.\n *\n * @param params - An object mapping parameter names to their string values.\n * @param currentRoutePath - The current route path, used for constructing error messages.\n * @returns A function that replaces a matched parameter placeholder (e.g., ':id') with its corresponding value.\n */\nfunction handlePrerenderParamsReplacement(\n  params: Record<string, string>,\n  currentRoutePath: string,\n): (substring: string, ...args: unknown[]) => string {\n  return (match) => {\n    const parameterName = match.slice(1);\n    const value = params[parameterName];\n    if (typeof value !== 'string') {\n      throw new Error(\n        `The 'getPrerenderParams' function defined for the '${stripLeadingSlash(currentRoutePath)}' route ` +\n          `returned a non-string value for parameter '${parameterName}'. ` +\n          `Please make sure the 'getPrerenderParams' function returns values for all parameters ` +\n          'specified in this route.',\n      );\n    }\n\n    return parameterName === '**' ? `/${value}` : value;\n  };\n}\n\n/**\n * Resolves the `redirectTo` property for a given route.\n *\n * This function processes the `redirectTo` property to ensure that it correctly\n * resolves relative to the current route path. If `redirectTo` is an absolute path,\n * it is returned as is. If it is a relative path, it is resolved based on the current route path.\n *","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/ssr/src/routes/ng-routes.ts#L502-L538","documentation":"When prerendering a parameterized route, the `getPrerenderParams` callback returns values that are substituted into the route path. This error fires when the returned value for a parameter is not a `string` (undefined, number, object, etc.), so the path template cannot be safely expanded. It guarantees the generated route tree contains valid string-only parameter values.","triggerScenarios":"`getPrerenderParams: async () => [{ id: 123 }]` (number instead of string), a missing key for one of the route's `:param` segments, or returning `undefined` from an async lookup in `handlePrerenderParamsReplacement` during `prerenderRoutes`/build.","commonSituations":"Fetching IDs from a CMS/API where some records return numeric IDs or null; forgetting a parameter defined in the route (e.g. route has `:category/:slug` but callback only returns `slug`); TypeScript not strict so objects lack required keys.","solutions":["Return a string for every parameter in the route: `{ id: String(product.id) }` or fetch IDs as strings.","Ensure the callback returns one object per parameter set, covering ALL parameters declared in the route path.","Add runtime validation/filtering: drop records with missing values before returning them.","Run `ng build` with a `console.log` inside `getPrerenderParams` to see the exact offending parameter and value."],"exampleFix":"// before\ngetPrerenderParams: async () => {\n  const products = await getProducts();\n  return products.map(p => ({ id: p.id })); // p.id is a number\n}\n// after\ngetPrerenderParams: async () => {\n  const products = await getProducts();\n  return products.filter(p => p.id != null).map(p => ({ id: String(p.id) }));\n}","handlingStrategy":"validation","validationCode":"// validate before returning from getPrerenderParams\nconst raw = await fetchIds();\nconst params = raw.map(p => ({ id: String(p.id) }));\nfor (const p of params) {\n  if (typeof p.id !== 'string') throw new Error('id must be a string');\n}\nreturn params;","typeGuard":"function hasStringParams(route: string, obj: Record<string, unknown>): obj is Record<string, string> {\n  const names = [...route.matchAll(/:(\\w+)/g)].map(m => m[1]);\n  return names.every(n => typeof obj[n] === 'string');\n}","tryCatchPattern":"try {\n  await prerenderRoutes(...);\n} catch (e) {\n  const m = /non-string value for parameter '(\\w+)'/.exec(e.message);\n  if (m) console.error(`Parameter '${m[1]}' must be a string in getPrerenderParams`);\n  else throw e;\n}","preventionTips":["Coerce all IDs to strings (`String(id)`) before returning from `getPrerenderParams`.","Return one object per generated page covering every `:param` in the route path.","Filter out records with null/undefined values before mapping to params.","Enable strict TypeScript so missing object keys are caught at compile time."],"tags":["angular","ssr","prerender","getprerenderparams","type-error"],"backgroundTag":"getprerenderparams-invalid-value","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}