facebook/react · error · 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

After resolving a client module in the manifest, the server checks consistency: if the manifest marks the module async (resolvedModuleData.async === true, meaning its chunks must be awaited as ESM) AND the client reference was also created as async ($$async), but the module was actually obtained through the CommonJS require/register proxy path, it throws. The async boundary would be silently lost through the CJS proxy, breaking chunk loading on the client, so this is treated as a bundler-integration bug.

Source

Thrown at packages/react-server-dom-unbundled/src/server/ReactFlightServerConfigUnbundledBundler.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. Load 'use client' modules through the ESM loader pipeline (ReactFlightWebpackNodeLoader in module.rules / node --experimental-loader) instead of the CJS register hook
  2. Regenerate the client manifest with the same toolchain version you run with, so 'async' flags match how modules are actually loaded
  3. If you create client references manually, do not set $$async for modules you load via require()

Example fix

// before: CJS register hook serving async-marked modules
require('react-server-dom-webpack/node-register');
const ClientChart = require('./Chart'); // manifest says async ESM -> throws

// after: run the module graph through the ESM loader
// webpack server config / node loader chain:
module: {rules: [{test: /\.(js|ts|jsx|tsx)$/,
  loader: 'react-server-dom-webpack/node-loader'}]}
Defensive patterns

Strategy: validation

Validate before calling

// Detect the mismatch before render: async manifest entries must not be required
const isCjsProxy = (mod) => mod != null && (mod.__esModule !== true || typeof mod.default === 'undefined' && mod.constructor?.name === 'Module' === false);
for (const [path, entry] of Object.entries(clientManifest)) {
  if (entry.async && usedRequireFor(path)) {
    throw new Error(`${path} is async ESM in the manifest but was loaded via require()`);
  }
}

Type guard

function isAsyncManifestEntry(entry) {
  return entry != null && entry.async === true;
}

Prevention

When it happens

Trigger: Using the CJS register() hook (ReactFlightWebpackNodeRegister) to load a 'use client' module whose manifest entry was emitted as async ESM; mixing import and require graphs so the server holds a CJS proxy of a module the manifest declares async; hand-creating client references with $$async true over a require()d module.

Common situations: Switching part of a server to ESM while the register hook still compiles client modules as CJS; version skew between the plugin that emitted the manifest and the loader/register used at runtime; custom servers that require() client modules for type checks but register them as references.

Related errors


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