{"record":{"id":"6586178c42b62f1a","repo":"remix-run/react-router","slug":"path-path-requires-param-param-but-it-wa","errorCode":null,"errorMessage":"Path '${path}' requires param '${param}' but it was not provided","messagePattern":"Path '(.+?)' requires param '(.+?)' but it was not provided","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router/lib/href.ts","lineNumber":58,"sourceCode":" * @category Utils\n * @mode framework\n * @param path The route path to resolve\n * @param args The route params to use when resolving the path\n * @returns The resolved URL path\n */\nexport function href<Path extends keyof Args>(\n  path: Path,\n  ...args: Args[Path]\n): string {\n  let params = args[0];\n  let result = trimTrailingSplat(path) // Ignore trailing / and /*, we'll handle it below\n    .replace(\n      /\\/:([\\w-]+)(\\?)?/g, // same regex as in .\\router\\utils.ts: compilePath().\n      (_: string, param: string, questionMark: string | undefined) => {\n        const isRequired = questionMark === undefined;\n        const value = params?.[param];\n        if (isRequired && value === undefined) {\n          throw new Error(\n            `Path '${path}' requires param '${param}' but it was not provided`,\n          );\n        }\n        return value == null ? \"\" : \"/\" + encodePathParam(stringify(value));\n      },\n    );\n\n  if (path.endsWith(\"*\")) {\n    // treat trailing splat the same way as compilePath, and force it to be as if it were `/*`.\n    // `react-router typegen` will not generate the params for a malformed splat,\n    // causing a type error, but we can still do the correct thing here.\n    const value = params?.[\"*\"];\n    if (value !== undefined) {\n      result +=\n        \"/\" + stringify(value).split(\"/\").map(encodePathParam).join(\"/\");\n    }\n  }\n","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router/lib/href.ts#L40-L76","documentation":"`href()` interpolates `/param` segments of a route path string. A required segment (`:name` with no trailing `?`) had no value in the `params` argument, so it cannot be filled in. This is the runtime counterpart of a check that `react-router typegen` performs at compile time.","triggerScenarios":"Calling `href('/users/:userId/posts/:postId', { userId: '1' })` where `:postId` is required but omitted; passing `undefined` for a required param; a refactor that adds a new required param to a route but not all `href()` call sites are updated.","commonSituations":"Dynamic routes whose params change during development; passing `params` from a loosely-typed source (search params, JSON) that omits a key; bypassing TypeScript by casting `params as any`.","solutions":["Provide a value for every required `:param` in the params object.","If the param should be optional, declare the route segment as `:param?`.","Regenerate types (`pnpm run typegen`) so TypeScript catches missing params at compile time.","Audit every `href()` call site for the route after changing its param shape."],"exampleFix":"// before\nhref('/users/:userId/posts/:postId', { userId: '1' });\n\n// after\nhref('/users/:userId/posts/:postId', { userId: '1', postId: '42' });","handlingStrategy":"validation","validationCode":"function hasAllRequiredParams(path: string, params: Record<string, unknown>): boolean {\n  const required = (path.match(/\\/:([\\w-]+)(?!\\?)/g) ?? []).map((m) => m.slice(2));\n  return required.every((p) => params[p] != null);\n}\nif (!hasAllRequiredParams(path, params)) throw new Error('Missing required params');","typeGuard":"function isCompleteParams(path: string, params: Record<string, unknown>): params is Record<string, string> {\n  const required = (path.match(/\\/:([\\w-]+)(?!\\?)/g) ?? []).map((m) => m.slice(2));\n  return required.every((p) => typeof params[p] === 'string' && params[p].length > 0);\n}","tryCatchPattern":null,"preventionTips":["Regenerate types after every route-shape change.","Don't cast params to `any`; let the generated `href` overloads type-check args.","Centralize route path strings as typed constants."],"tags":["href","routing","params","typegen"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}