remix-run/react-router · error
You cannot call `runClientMiddleware()` from a static…
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
In SSR, middleware runs outside dataStrategy so that middleware Responses (redirects, errors) can bubble up as the HTTP response. A static handler's dataStrategy therefore receives a runClientMiddleware that is a throwing stub (lib/router/router.ts:6573); calling it means a browser-oriented dataStrategy was reused on the server.
Solutions
- Split the strategy per environment: only call runClientMiddleware when running in the browser (typeof window !== 'undefined')
- On the server, let query()/queryRoute() drive middleware themselves (respond API) instead of calling it from dataStrategy
- Pass a separate dataStrategy option to createStaticHandler vs createBrowserRouter
Example fix
// before
const dataStrategy = async (args) => args.runClientMiddleware(async () => args.fetch())
createBrowserRouter({ dataStrategy })
createStaticHandler({ dataStrategy }) // throws in SSR
// after
const dataStrategy = async (args) =>
typeof window === 'undefined'
? args.fetch()
: args.runClientMiddleware(async () => args.fetch()) Defensive patterns
Strategy: type-guard
Validate before calling
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'; const dataStrategy = async (args) => isBrowser ? args.runClientMiddleware(() => args.fetch()) : args.fetch();
Type guard
function isStaticHandlerArgs(args: DataStrategyFunctionArgs): boolean {
return typeof window === 'undefined';
} Prevention
- Keep separate dataStrategy implementations for client router and static handler
- Branch on environment (window check) before touching runClientMiddleware
- On the server, rely on query()/queryRoute() to run middleware outside dataStrategy
When it happens
Trigger: Sharing one custom dataStrategy between createBrowserRouter and createStaticHandler and unconditionally calling args.runClientMiddleware(...); a fetcher/handler strategy copied from client code into an express/node SSR setup; invoking the single-fetch default strategy shape inside query() with middleware enabled.
Common situations: Custom dataStrategy with tracing/caching wrappers deployed to both environments; integration tests running the client strategy through a static handler; enabling middleware after the dataStrategy was already written for client-only behavior.
Related errors
- Cannot call `runClientMiddleware()` from within an…
- Failed to clone server response
- Missing body in server response
- No value found for context
- You may only call `next()` once per middleware
AI-assisted analysis of remix-run/react-router@7aea711dd1 (2026-08-18).
Data as JSON: /api/errors/8fa3563f438f11e7.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router/lib/router/router.ts:6552
}
// 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 7aea711dd1)