remix-run/react-router · error · Error
Cannot handle enhanced server action without decodeReply and
Error message
Cannot handle enhanced server action without decodeReply and loadServerAction functions
What it means
`handleServerAction` received a request carrying an `rsc-action-id` header (an enhanced/server-component action call) but the React Server functions `decodeReply` and/or `loadServerAction` were not provided. Without them the runtime cannot decode the action arguments or look up the action by id.
Source
Thrown at packages/react-router/lib/rsc/server.rsc.ts:679
formState?: ReactFormState;
}
| Response
| undefined
> {
const getRevalidationRequest = () =>
new Request(request.url, {
method: "GET",
headers: request.headers,
signal: request.signal,
});
const isFormRequest = canDecodeWithFormData(
request.headers.get("Content-Type"),
);
const actionId = request.headers.get("rsc-action-id");
if (actionId) {
if (!decodeReply || !loadServerAction) {
throw new Error(
"Cannot handle enhanced server action without decodeReply and loadServerAction functions",
);
}
const reply = isFormRequest
? await request.formData()
: await request.text();
const actionArgs = await decodeReply(reply, { temporaryReferences });
const action = await loadServerAction(actionId);
const serverAction = action.bind(null, ...actionArgs);
let actionResult = Promise.resolve(serverAction());
try {
// Wait for actions to finish regardless of state
await actionResult;
} catch (error) {
if (isResponse(error)) {View on GitHub (pinned to 1fd704a7da)
Solutions
- Pass `decodeReply` and `loadServerAction` from your `react-server-dom-*/server` module into `handleServerAction`/`createRSCRequestHandler`.
- Confirm the rsd bundle version matches the React Router RSC runtime version.
- If you don't intend to support enhanced server actions, ensure clients don't send the `rsc-action-id` header.
Example fix
// before
handleServerAction({ request });
// after
import { decodeReply, loadServerAction } from 'react-server-dom-webpack/server';
handleServerAction({ request, decodeReply, loadServerAction }); Defensive patterns
Strategy: validation
Validate before calling
function assertRscFns(opts: { decodeReply?: unknown; loadServerAction?: unknown }) {
if (!opts.decodeReply || !opts.loadServerAction) {
throw new Error('RSC server actions require decodeReply and loadServerAction');
}
}
assertRscFns({ decodeReply, loadServerAction }); Type guard
function hasEnhancedActionFns(o: any): o is { decodeReply: Function; loadServerAction: Function } {
return typeof o.decodeReply === 'function' && typeof o.loadServerAction === 'function';
} Prevention
- Always wire all four decode functions (decodeReply, decodeAction, decodeFormState, loadServerAction) when constructing the RSC handler.
- Pin rsd version to match the React Router RSC runtime.
- Reject requests with `rsc-action-id` at the edge if you don't support enhanced actions.
When it happens
Trigger: Calling `handleServerAction(request, ...)` (or wiring a custom server action endpoint) without passing the `decodeReply` and `loadServerAction` functions sourced from `react-server-dom-xyz/server`. The request still reached this code path because of the `rsc-action-id` header.
Common situations: Building a custom RSC server adapter and forgetting to forward the rsd functions; partial RSC setup where only some handlers are wired; a misconfigured `createRSCRequestHandler` that drops the options.
Related errors
- Cannot handle form actions without a decodeAction function
- The "@vitejs/plugin-rsc" plugin should be placed after the R
- ${configResult.error}
- When using the React Router `basename` and the Vite `base` c
- React Router presets must have a `name` property defined.
AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12).
Data as JSON: /api/errors/344fe41c77d93ba5.
Report an issue: GitHub.