facebook/react · critical · Error

The module "${modulePath}" is marked as an async ESM module

Error message

The module "${modulePath}" is marked as an async ESM module but was loaded as a CJS proxy. This is probably a bug in the React Server Components bundler.

What it means

resolveClientReference throws when the client manifest marks the module as async ESM (resolvedModuleData.async === true) and the reference itself is flagged $$async, yet the reference was loaded through the CommonJS module-proxy path. The bundler produced contradictory metadata — the client would load the module with the wrong semantics — so React refuses to serialize it and reports a bundler bug.

Source

Thrown at packages/react-server-dom-webpack/src/server/ReactFlightServerConfigWebpackBundler.js:75

    // which contains this name as well.
    // TODO: It's unfortunate that we now have to parse this string. We should
    // probably go back to encoding path and name separately on the client reference.
    const idx = modulePath.lastIndexOf('#');
    if (idx !== -1) {
      name = modulePath.slice(idx + 1);
      resolvedModuleData = config[modulePath.slice(0, idx)];
    }
    if (!resolvedModuleData) {
      throw new Error(
        'Could not find the module "' +
          modulePath +
          '" in the React Client Manifest. ' +
          'This is probably a bug in the React Server Components bundler.',
      );
    }
  }
  if (resolvedModuleData.async === true && clientReference.$$async === true) {
    throw new Error(
      'The module "' +
        modulePath +
        '" is marked as an async ESM module but was loaded as a CJS proxy. ' +
        'This is probably a bug in the React Server Components bundler.',
    );
  }
  if (resolvedModuleData.async === true || clientReference.$$async === true) {
    return [resolvedModuleData.id, resolvedModuleData.chunks, name, 1];
  } else {
    return [resolvedModuleData.id, resolvedModuleData.chunks, name];
  }
}

export function getServerReferenceId<T>(
  config: ClientManifest,
  serverReference: ServerReference<T>,
): ServerReferenceId {
  return serverReference.$$id;

View on GitHub (pinned to eafeac097b)

Solutions

  1. Pin matching versions of react, react-server-dom-webpack, and the RSC bundler plugin, then clean-rebuild everything
  2. Avoid top-level await in 'use client' modules, or make the client build emit ESM consistently so the async path matches
  3. In custom integrations, do not register async modules through createClientModuleProxy — keep $$async flags consistent with the manifest
Defensive patterns

Strategy: retry

Try / catch

try {
  const {pipe} = renderToPipeableStream(<App/>, {onError: e => log(e)});
} catch (e) {
  if (String(e.message).includes('async ESM module but was loaded as a CJS proxy')) {
    // Bundler metadata conflict: align plugin/runtime versions and clean-rebuild, then retry once.
  }
}

Prevention

When it happens

Trigger: A 'use client' module using top-level await / async ESM output while the RSC integration wraps it with createClientModuleProxy (CJS semantics); mixing ESM ('type': 'module') client output with CJS interop in one setup; a react-server-dom-webpack runtime at a different version than the webpack RSC loader plugin, changing the proxy strategy.

Common situations: Upgrading the RSC plugin or react-server-dom-webpack separately without a clean rebuild; enabling top-level await in client components mid-project; custom bundler integrations reusing React's plugin with inconsistent module formats.

Related errors


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