{"record":{"id":"c324ed36ef63fb31","repo":"remix-run/remix","slug":"missing-params","errorCode":null,"errorMessage":"missing-params","messagePattern":"missing-params","errorType":"validation","errorClass":"CreateHrefError","httpStatus":null,"severity":"error","filePath":"packages/route-pattern/src/lib/href.ts","lineNumber":220,"sourceCode":"        ) {\n          i += 1\n        }\n        continue\n      }\n      // oxfmt-ignore\n      stack[stack.length - 1].href +=\n        part.type === 'pathname' && token.type === ':' ? encodePathnameVariableParam(pattern, token.name, value) :\n        part.type === 'pathname' && token.type === '*' ? encodePathnameWildcard(value) :\n        part.type === 'hostname' && token.type === ':' ? validateHostnameVariable(value) :\n        part.type === 'hostname' && token.type === '*' ? validateHostnameWildcard(value) :\n        unreachable()\n      i += 1\n      continue\n    }\n    unreachable(token.type)\n  }\n  if (missingParams.length > 0) {\n    throw new CreateHrefError({\n      type: 'missing-params',\n      pattern,\n      missingParams,\n      params,\n    })\n  }\n  if (stack.length !== 1) unreachable()\n  return stack[0].href\n}\n\nfunction hrefSearch(\n  constraints: RoutePatternParts['search'],\n  searchParams?: CreateHrefSearchParams,\n): string | undefined {\n  let urlSearchParams =\n    searchParams instanceof URLSearchParams\n      ? new URLSearchParams(searchParams)\n      : new URLSearchParams()","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/route-pattern/src/lib/href.ts#L202-L238","documentation":"After serializing a pattern part, one or more named params were referenced by the pattern but missing from the supplied params object (and were not optional). The error carries the list of missing param names so callers know exactly what to supply.","triggerScenarios":"Calling href/createHref on a pattern like `/users/:id/posts/:postId` with params missing `postId` (or all params). Only thrown after the whole part is processed, once all gaps are collected.","commonSituations":"Building links programmatically from partial objects; type mismatches (string vs number keys); patterns updated to require new params while call sites weren't; typos in param names (postId vs postID).","solutions":["Supply every required param listed in error.missingParams","Make genuinely optional segments optional in the pattern with parentheses: `/users/:id(/edit)`","Derive params from a typed source (e.g. route param types) so missing keys are compile-time errors","Log the pattern alongside params at build time in dev to catch bad link generation"],"exampleFix":"// before\nhref(userPostPattern, { id: '1' }) // postId missing\n\n// after\nhref(userPostPattern, { id: '1', postId: '42' })","handlingStrategy":"validation","validationCode":"let required = pattern.pathname.tokens.filter(t => t.type === ':').map(t => t.name)\nlet missing = required.filter(n => params[n] == null)\nif (missing.length) throw new Error(`Missing params: ${missing.join(', ')}`)","typeGuard":"function hasAllParams(pattern: RoutePattern, params: Record<string, unknown>): boolean {\n  return collectParamNames(pattern).every(name => params[name] != null)\n}","tryCatchPattern":"try { href(pattern, params) } catch (e) { if (e?.type === 'missing-params' && e.missingParams) { /* fill or skip */ } }","preventionTips":["Derive link params from typed route data","Use optional segments for truly optional params","Log missingParams in dev builds"],"tags":["route-pattern","href","params"],"backgroundTag":"missing-route-params","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}