remix-run/react-router · error · Error

Unable to decode RSC response

Error message

Unable to decode RSC response

What it means

This is the RSC counterpart of the single-fetch decode error: responses for navigations/actions are decoded with `createFromReadableStream`, and any failure during decode lands in this catch, which throws a bare `Error("Unable to decode RSC response", { cause })` because the consumed body cannot be cloned for diagnostics. The original failure is preserved in `cause`. The bytes received were simply not a decodable RSC stream.

Source

Thrown at packages/react-router/lib/rsc/browser.tsx:650

      const dataKey = isMutationMethod(request.method)
        ? "actionData"
        : "loaderData";
      for (let [routeId, data] of Object.entries(payload[dataKey] || {})) {
        results.routes[routeId] = { data };
      }
      if (payload.errors) {
        for (let [routeId, error] of Object.entries(payload.errors)) {
          results.routes[routeId] = { error };
        }
      }
      return { status: res.status, data: results };
    } catch (cause) {
      // Can't clone after consuming the body via decode so we can't include the
      // body here.  In an ideal world we'd look for an RSC  content type here,
      // or even X-Remix-Response but then folks can't statically deploy their
      // prerendered .rsc files to a CDN unless they can tell that CDN to add
      // special headers to those certain files - which is a bit restrictive.
      throw new Error("Unable to decode RSC response", { cause });
    }
  };
}

/**
 * Props for the {@link unstable_RSCHydratedRouter} component.
 *
 * @name unstable_RSCHydratedRouterProps
 * @category Types
 */
export interface RSCHydratedRouterProps {
  /**
   * Your `react-server-dom-xyz/client`'s `createFromReadableStream` function,
   * used to decode payloads from the server.
   */
  createFromReadableStream: BrowserCreateFromReadableStreamFunction;
  /**
   * Optional fetch implementation. Defaults to global [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch).

View on GitHub (pinned to 7aea711dd1)

Solutions

  1. Inspect the failing request's raw response in the network tab; if it's HTML or empty, fix the layer that produced it (proxy, auth, 404 handler) to pass RSC requests through.
  2. Disable content transformation/compression for RSC responses at your CDN/proxy.
  3. After upgrading React Router / plugin-rsc, redeploy and hard reload so encoder and decoder versions match.
  4. Read `error.cause` in your error boundary logging to capture the underlying decode failure.
Defensive patterns

Strategy: retry

Try / catch

export function ErrorBoundary() {
  const error = useRouteError();
  if (error instanceof Error && /decode RSC response/i.test(error.message)) {
    // log the underlying cause, then recover with a full reload
    console.error(error.cause);
    return <button onClick={() => window.location.reload()}>Reload</button>;
  }
  throw error;
}

Prevention

When it happens

Trigger: HTML error pages (404/500/login) returned where an RSC stream was expected; compression or encoding corruption by proxies; partial/truncated responses from dropped connections; React server/client serialization version mismatch after upgrades where old clients decode new streams.

Common situations: Auth gateways intercepting `.rsc` requests; aggressive CDN transformations (minify/compress on-the-fly); flaky mobile connections truncating streams; upgrading @vitejs/plugin-rsc or react versions while browsers hold cached old bundles.

Understand the failure class

Related errors


AI-assisted analysis of remix-run/react-router@7aea711dd1 (2026-08-18). Data as JSON: /api/errors/4033b5b4ce67b43f. Report an issue: GitHub.