remix-run/react-router · error · Error

You cannot call `runClientMiddleware()` from a static handle

Error message

You cannot call `runClientMiddleware()` from a static handler `dataStrategy`. Middleware is run outside of `dataStrategy` during SSR in order to bubble up the Response.  You can enable middleware via the `respond` API in `query`/`queryRoute`

What it means

When `createStaticHandler` runs a custom `dataStrategy` during SSR (`isStaticHandler === true`), the `runClientMiddleware` field is a function that always throws. Middleware cannot run from within `dataStrategy` during SSR because the framework must let the Response bubble up through the static handler's `respond` API instead.

Source

Thrown at packages/react-router/lib/router/router.ts:6573

  }

  // Send all matches here to allow for a middleware-type implementation.
  // handler will be a no-op for unneeded routes and we filter those results
  // back out below.
  let dataStrategyArgs: Omit<
    DataStrategyFunctionArgs<unknown>,
    "fetcherKey" | "runClientMiddleware"
  > = {
    request,
    url: createDataFunctionUrl(request, path),
    pattern: getRoutePattern(matches),
    params: matches[0].params,
    context: scopedContext,
    matches,
  };
  let runClientMiddleware = isStaticHandler
    ? () => {
        throw new Error(
          "You cannot call `runClientMiddleware()` from a static handler " +
            "`dataStrategy`. Middleware is run outside of `dataStrategy` during " +
            "SSR in order to bubble up the Response.  You can enable middleware " +
            "via the `respond` API in `query`/`queryRoute`",
        );
      }
    : (cb: DataStrategyFunction<RouterContextProvider>) => {
        let typedDataStrategyArgs =
          dataStrategyArgs as DataStrategyFunctionArgs<RouterContextProvider>;
        return runClientMiddlewarePipeline(typedDataStrategyArgs, () => {
          return cb({
            ...typedDataStrategyArgs,
            fetcherKey,
            runClientMiddleware: () => {
              throw new Error(
                "Cannot call `runClientMiddleware()` from within an " +
                  "`runClientMiddleware` handler",
              );

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Do not call `runClientMiddleware()` from a `dataStrategy` used with `createStaticHandler`.
  2. Branch the dataStrategy: run middleware on the client only, or drive SSR middleware via the `respond` API in `query`/`queryRoute`.
  3. Factor the shared logic out so the SSR variant omits the `runClientMiddleware` call.

Example fix

// before
createStaticHandler(routes, {
  dataStrategy: (args) => args.runClientMiddleware(() => defaultStrategy(args)),
});

// after
createStaticHandler(routes, {
  dataStrategy: defaultStrategy, // no runClientMiddleware on SSR
});
Defensive patterns

Strategy: validation

Validate before calling

function isStaticDataStrategyArgs(args: any): boolean {
  return typeof args.runClientMiddleware === 'function' && /static/.test(args.runClientMiddleware.toString());
}
// branch the dataStrategy:
const dataStrategy = (args) =>
  isStaticDataStrategyArgs(args)
    ? defaultStrategy(args)
    : args.runClientMiddleware(() => defaultStrategy(args));

Prevention

When it happens

Trigger: User-supplied `dataStrategy` calls `args.runClientMiddleware(...)` while the handler is the static (SSR) one created by `createStaticHandler({ dataStrategy })`.

Common situations: Sharing one `dataStrategy` between client and server without branching on context; copy-pasting a client-side middleware-driving dataStrategy into `createStaticHandler`.

Related errors


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