remix-run/react-router · error · SingleFetchNoResultError

No result found for routeId "${routeId}"

Error message

No result found for routeId "${routeId}"

What it means

In single-fetch mode the server returns a map of per-route results; this error is thrown when the client asks for `result.routes[routeId]` for a route it is revalidating and the entry is `null`/`undefined`. It uses the dedicated `SingleFetchNoResultError` class because the router and middleware logic specifically detect it (e.g., to swap in middleware errors). In practice the server response simply did not include data for a route the client expected to have results for.

Source

Thrown at packages/react-router/lib/dom/ssr/single-fetch.tsx:753

      revalidate,
      reload,
      replace,
      status,
    } = result.redirect;
    throw redirect(location, {
      status,
      headers: {
        // Three R's of redirecting (lol Veep)
        ...(revalidate ? { "X-Remix-Revalidate": "yes" } : null),
        ...(reload ? { "X-Remix-Reload-Document": "yes" } : null),
        ...(replace ? { "X-Remix-Replace": "yes" } : null),
      },
    });
  }

  let routeResult = result.routes[routeId];
  if (routeResult == null) {
    throw new SingleFetchNoResultError(
      `No result found for routeId "${routeId}"`,
    );
  } else if ("error" in routeResult) {
    throw routeResult.error;
  } else if ("data" in routeResult) {
    return routeResult.data;
  } else {
    throw new Error(`Invalid response found for routeId "${routeId}"`);
  }
}

function createDeferred<T = unknown>() {
  let resolve: (val: T) => Promise<void>;
  let reject: (error: unknown) => Promise<void>;
  let promise = new Promise<T>((res, rej) => {
    resolve = async (val: T) => {
      res(val);
      try {

View on GitHub (pinned to 6beaca3952)

Solutions

  1. Hard reload to resync the client's route set with the server after a deploy.
  2. If you customize `handleRequest` or the single-fetch serialization, make sure every route id the client revalidates appears in the returned routes map.
  3. Only call `serverLoader()` from routes whose loader actually ran on the server (routes present in the matched request).
  4. Reproduce with the `.data` request visible in the network tab and compare the route ids in the payload against the ids of matched routes.
Defensive patterns

Strategy: try-catch

Try / catch

export function ErrorBoundary() {
  const error = useRouteError();
  if (error instanceof Error && error.message.includes("No result found for routeId")) {
    return <Link reloadDocument to={location.pathname}>Reload</Link>;
  }
  throw error;
}

Prevention

When it happens

Trigger: A clientLoader calling `serverLoader()` for a route that was not part of the server's single-fetch request; version skew where the client revalidates a route the freshly-deployed server no longer runs; a custom server/`handleRequest` that filters which loader results get serialized into the `.data` response; fetcher loads racing a navigation that removed the route.

Common situations: Hitting the error immediately after a deploy that added/removed routes while the browser had the app open; wrapping the server request pipeline with custom logic that drops route results; using `patchRoutesOnNavigation`/lazy route discovery with a server that does not know the new route yet.

Related errors


AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18). Data as JSON: /api/errors/3448da4dfd3764b4. Report an issue: GitHub.