vercel/next.js · error · Error

An unexpected response was received from the server.

Error message

An unexpected response was received from the server.

What it means

Thrown at server-action-reducer.ts:226-234 when a Server Action response is neither an RSC payload (`text/x-component`) nor carries an `x-action-redirect` header. The client expects every valid action response to be Flight data or an external redirect; anything else is treated as a protocol violation and surfaced as a generic `Error` whose message is the response body if it was a `text/plain` error, otherwise this literal string.

Source

Thrown at packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts:234

    : undefined

  const contentType = res.headers.get('content-type')
  const isRscResponse = !!(
    contentType && contentType.startsWith(RSC_CONTENT_TYPE_HEADER)
  )

  // Handle invalid server action responses.
  // A valid response must have `content-type: text/x-component`, unless it's an external redirect.
  // (external redirects have an 'x-action-redirect' header, but the body is an empty 'text/plain')
  if (!isRscResponse && !redirectLocation) {
    // The server can respond with a text/plain error message, but we'll fallback to something generic
    // if there isn't one.
    const message =
      res.status >= 400 && contentType === 'text/plain'
        ? await res.text()
        : 'An unexpected response was received from the server.'

    throw new Error(message)
  }

  let actionResult: FetchServerActionResult['actionResult']
  let actionFlightData: FetchServerActionResult['actionFlightData']
  let actionFlightDataRenderedSearch: FetchServerActionResult['actionFlightDataRenderedSearch']
  let couldBeIntercepted: boolean = false

  if (isRscResponse) {
    // Server action redirect responses carry the Flight data of the redirect
    // target, which may be prerendered with a completeness marker byte
    // prepended. Strip it before passing to Flight.
    const responsePromise = redirectLocation
      ? processFetch(res).then(({ response: r }) => r)
      : Promise.resolve(res)

    const response: ActionFlightResponse = await createFromFetch(
      responsePromise,
      {

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Open the browser devtools Network tab and inspect the action POST response body and status code to identify what the server actually returned.
  2. Check server logs for the unhandled exception that produced an HTML error page instead of an RSC error payload.
  3. Verify no middleware/proxy is intercepting POSTs to the page URL and returning a non-Flight response.
  4. Confirm `basePath` and `assetPrefix` are correct so the action POST reaches the Next.js server.

Example fix

// before: action throws an unhandled error -> HTML error page -> generic message
'use server'
export async function action() {
  throw 'oops' // non-Error throw produces an opaque server error
}

// after: throw a proper Error so the server returns a Flight error payload
'use server'
export async function action() {
  throw new Error('Something went wrong')
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Cannot prevent from the client; validate server-side that actions
// return proper Flight responses. Ensure actions throw Error subclasses
// so Next.js returns RSC error payloads, not HTML error pages.

Type guard

function isLikelyFlightResponse(res: Response): boolean {
  const ct = res.headers.get('content-type') ?? ''
  return ct.startsWith('text/x-component')
}

Try / catch

'use client'
try {
  await myAction()
} catch (err) {
  // err.message may be the server's text/plain body or the generic string.
  console.error('Action failed:', err instanceof Error ? err.message : err)
  // Show user-facing fallback UI
}

Prevention

When it happens

Trigger: The server returned HTML (e.g. a 500 error page, a login redirect, a WAF challenge) instead of an RSC response; a proxy/CDN intercepted the POST and returned a non-Flight body; the action threw an unhandled server exception that Next.js rendered as an error page; the route handler returned a `Response` with the wrong content type.

Common situations: Auth middleware redirecting the action POST to a login HTML page; a reverse proxy returning a 502/HTML error page; the server crashing mid-action and returning the default error document; misconfigured `basePath`/`assetPrefix` causing the POST to hit a static host returning HTML.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/d43b172000cf97ed. Report an issue: GitHub.