facebook/react · error · Error

Cannot await or return from a thenable. You cannot await a c

Error message

Cannot await or return from a thenable. You cannot await a client module from a server component.

What it means

In React Server Components, each named export of a 'use client' module is wrapped on the server by deepProxyHandlers, an opaque Proxy. Reading the '.then' property of that proxy — which is exactly what await, return-from-async, Promise.resolve(), or use() do to detect thenables — throws, because resolving the thenable would require the real client-side value, which never loads on the server. Client references may only be rendered as components or forwarded as props.

Source

Thrown at packages/react-server-dom-webpack/src/ReactFlightWebpackReferences.js:190

      // React looks for debugInfo on thenables.
      case '_debugInfo':
        return undefined;
      // Avoid this attempting to be serialized.
      case 'toJSON':
        return undefined;
      case Symbol.toPrimitive:
        // $FlowFixMe[prop-missing]
        return Object.prototype[Symbol.toPrimitive];
      case Symbol.toStringTag:
        // $FlowFixMe[prop-missing]
        return Object.prototype[Symbol.toStringTag];
      case 'Provider':
        // Context.Provider === Context in React, so return the same reference.
        // This allows server components to render <ClientContext.Provider>
        // which will be serialized and executed on the client.
        return receiver;
      case 'then':
        throw new Error(
          `Cannot await or return from a thenable. ` +
            `You cannot await a client module from a server component.`,
        );
    }
    // eslint-disable-next-line react-internal/safe-string-coercion
    const expression = String(target.name) + '.' + String(name);
    throw new Error(
      `Cannot access ${expression} on the server. ` +
        'You cannot dot into a client module from a server component. ' +
        'You can only pass the imported name through.',
    );
  },
  set: function () {
    throw new Error('Cannot assign to a client module from a server module.');
  },
};

function getReference(target: Function, name: string | symbol): $FlowFixMe {

View on GitHub (pinned to eafeac097b)

Solutions

  1. Replace the dynamic import with a static import and pass the named export through: import {Chart} from './charts', then render <Chart/> or send it as a prop
  2. If the awaited logic must run on the server, move it into a module without the 'use client' directive
  3. If the module must load only in the browser, move the dynamic import inside a 'use client' component (e.g. next/dynamic with ssr:false there)
  4. For helpers that await unknown values, branch on client references first and forward them instead of awaiting

Example fix

// before (server component)
const { Chart } = await import('./charts'); // reads .then on client proxy -> throws

// after (server component)
import { Chart } from './charts'; // 'use client' module, used by reference only
export default function Page() {
  return <Chart data={...} />;
}
Defensive patterns

Strategy: type-guard

Validate before calling

const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');

// Run before awaiting any unknown value in server code:
if (isClientReference(value)) {
  // Never await it — render it or pass it through as a prop.
  return <Child mod={value} />;
}
const resolved = await value;

Type guard

const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');

function isClientReference(value) {
  return (
    value !== null &&
    (typeof value === 'object' || typeof value === 'function') &&
    value.$$typeof === CLIENT_REFERENCE_TAG
  );
}

Try / catch

try {
  result = await maybeClientRef;
} catch (e) {
  if (String(e.message).includes('Cannot await or return from a thenable')) {
    // Forward the reference instead of resolving it.
    return <ClientComponent mod={maybeClientRef} />;
  }
  throw e;
}

Prevention

When it happens

Trigger: Awaiting a named export of a client module in a server component: const {Chart} = await import('./charts'), await Chart, or Chart.then(...). Passing the export to Promise.resolve(Chart), use(Chart), or any 'value-or-promise' helper that probes typeof value.then === 'function'. Returning the client export from an async server component.

Common situations: Client-style lazy loading (dynamic import + await) copied into a server component; SSR-disabled patterns such as next/dynamic with ssr:false attempted inside RSC; generic resolvers that accept either a value or a promise receiving a client reference; React 19 use() given a client module export.

Related errors


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/fd9748b24e4584fa. Report an issue: GitHub.