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

  1. Pass `decodeReply` and `loadServerAction` from your `react-server-dom-*/server` module into `handleServerAction`/`createRSCRequestHandler`.
  2. Confirm the rsd bundle version matches the React Router RSC runtime version.
  3. 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

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


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