remix-run/react-router · error · Error
getRequest must be called from within a React Server render
Error message
getRequest must be called from within a React Server render context
What it means
`getRequest()` reads the current `Request` from an `AsyncLocalStorage`-backed server context. If `ServerStorage.getStore()` returns `undefined`, the call is outside any `run(...)` scope established by React Router's RSC runtime, so there is no current request and the function refuses to continue.
Source
Thrown at packages/react-router/lib/rsc/server.rsc.ts:98
type ServerContext = {
redirect?: Response;
request: Request;
runningAction: boolean;
};
const globalVar = (typeof globalThis !== "undefined" ? globalThis : global) as {
___reactRouterServerStorage___?: AsyncLocalStorage<ServerContext>;
};
const ServerStorage = (globalVar.___reactRouterServerStorage___ ??=
new AsyncLocalStorage<ServerContext>());
export function getRequest() {
const ctx = ServerStorage.getStore();
if (!ctx)
throw new Error(
"getRequest must be called from within a React Server render context",
);
return ctx.request;
}
export const redirect: typeof baseRedirect = (...args) => {
const response = baseRedirect(...args);
const ctx = ServerStorage.getStore();
if (ctx && ctx.runningAction) {
ctx.redirect = response;
}
return response;
};
export const redirectDocument: typeof baseRedirectDocument = (...args) => {
const response = baseRedirectDocument(...args);View on GitHub (pinned to 1fd704a7da)
Solutions
- Only call `getRequest()` from inside a server component, loader, action, or middleware running within the RSC render pass.
- If you need the request in a helper, accept it as a parameter from the loader/action rather than reading it implicitly.
- Confirm the RSC runtime is actually initialized (RSC Framework or RSC Data mode) — in non-RSC modes there is no server context.
Example fix
// before (module scope)
const req = getRequest(); // throws
// after (inside server component)
export default async function Route() {
const req = getRequest();
return <pre>{req.url}</pre>;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Only call inside the render pass; gate with an explicit flag
async function safeGetRequest() {
try {
return getRequest();
} catch {
return undefined;
}
} Type guard
function isInServerContext(): boolean {
return Boolean((globalThis as any).___reactRouterServerStorage___?.getStore?.());
} Try / catch
let request: Request | undefined;
try {
request = getRequest();
} catch {
request = undefined; // not in an RSC render scope
} Prevention
- Call `getRequest()` only inside server components/loaders/actions.
- Pass the Request explicitly to helpers instead of relying on implicit context.
- Confirm RSC mode is enabled before relying on server context.
When it happens
Trigger: Calling `getRequest()` (or RSC-aware `redirect`/`replace` that internally relies on it) at module top-level, in a utility called outside the React Server render pass, or in a worker/thread that doesn't inherit the AsyncLocalStorage context.
Common situations: Calling `getRequest()` from a standalone script, a route module's module scope (not inside loader/action/server component), or a non-RSC handler; using the RSC server API in a Data-mode or Declarative-mode app where no server render context is ever established.
Related errors
- The "@vitejs/plugin-rsc" plugin should be placed after the R
- ${configResult.error}
- When using the React Router `basename` and the Vite `base` c
- Prerender (data): Received a ${response.status} status code
- Module cannot have both a default export and a ServerCompone
AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12).
Data as JSON: /api/errors/298324e4343e21d0.
Report an issue: GitHub.