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
- Load 'use client' modules through the ESM loader pipeline (ReactFlightWebpackNodeLoader in module.rules / node --experimental-loader) instead of the CJS register hook
- Regenerate the client manifest with the same toolchain version you run with, so 'async' flags match how modules are actually loaded
- 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
- Pick one module system for the server graph: ESM loader pipeline or CJS register, never both
- Regenerate manifests whenever you switch loader vs register
- Do not hand-set $$async on manually registered client references
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
- The module "${modulePath}" is marked as an async ESM module
- The module "${modulePath}" is marked as an async ESM module
- Could not find the module "${modulePath}" in the React Clien
- Use react-server-dom-esm/client instead.
- Expected resolve to have been called before transformSource
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/52ae8aa37056d4df.
Report an issue: GitHub.