remix-run/react-router · error · Error

Path '${path}' requires param '${param}' but it was not prov

Error message

Path '${path}' requires param '${param}' but it was not provided

What it means

`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.

Source

Thrown at packages/react-router/lib/href.ts:58

 * @category Utils
 * @mode framework
 * @param path The route path to resolve
 * @param args The route params to use when resolving the path
 * @returns The resolved URL path
 */
export function href<Path extends keyof Args>(
  path: Path,
  ...args: Args[Path]
): string {
  let params = args[0];
  let result = trimTrailingSplat(path) // Ignore trailing / and /*, we'll handle it below
    .replace(
      /\/:([\w-]+)(\?)?/g, // same regex as in .\router\utils.ts: compilePath().
      (_: string, param: string, questionMark: string | undefined) => {
        const isRequired = questionMark === undefined;
        const value = params?.[param];
        if (isRequired && value === undefined) {
          throw new Error(
            `Path '${path}' requires param '${param}' but it was not provided`,
          );
        }
        return value == null ? "" : "/" + encodePathParam(stringify(value));
      },
    );

  if (path.endsWith("*")) {
    // treat trailing splat the same way as compilePath, and force it to be as if it were `/*`.
    // `react-router typegen` will not generate the params for a malformed splat,
    // causing a type error, but we can still do the correct thing here.
    const value = params?.["*"];
    if (value !== undefined) {
      result +=
        "/" + stringify(value).split("/").map(encodePathParam).join("/");
    }
  }

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Provide a value for every required `:param` in the params object.
  2. If the param should be optional, declare the route segment as `:param?`.
  3. Regenerate types (`pnpm run typegen`) so TypeScript catches missing params at compile time.
  4. Audit every `href()` call site for the route after changing its param shape.

Example fix

// before
href('/users/:userId/posts/:postId', { userId: '1' });

// after
href('/users/:userId/posts/:postId', { userId: '1', postId: '42' });
Defensive patterns

Strategy: validation

Validate before calling

function hasAllRequiredParams(path: string, params: Record<string, unknown>): boolean {
  const required = (path.match(/\/:([\w-]+)(?!\?)/g) ?? []).map((m) => m.slice(2));
  return required.every((p) => params[p] != null);
}
if (!hasAllRequiredParams(path, params)) throw new Error('Missing required params');

Type guard

function isCompleteParams(path: string, params: Record<string, unknown>): params is Record<string, string> {
  const required = (path.match(/\/:([\w-]+)(?!\?)/g) ?? []).map((m) => m.slice(2));
  return required.every((p) => typeof params[p] === 'string' && params[p].length > 0);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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`.

Related errors


AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12). Data as JSON: /api/errors/6586178c42b62f1a. Report an issue: GitHub.