facebook/react · error · Error

Attempted to load a Client Module outside the hosted root.

Error message

Attempted to load a Client Module outside the hosted root.

What it means

Server-side mirror of the client root check. When the Flight serializer encounters a client reference (an import of a 'use client' module), resolveClientReferenceMetadata strips the configured baseURL from the module's $$id to compute the relative module path sent to the client. If $$id does not start with baseURL — the string config passed to the esm server's renderToPipeableStream/renderToReadableStream — the module lies outside the hosted root and serialization aborts.

Solutions

  1. Pass the exact root the bundler used when it generated client module ids as the render config string
  2. Log clientReference.$$id when it fails and diff it against the configured baseURL to find the mismatch
  3. Rebuild the client bundle/manifest so the ids and the server's baseURL agree

Example fix

// before — bundler ids are file URLs, server passes an https base
renderToPipeableStream(<App/>, 'https://cdn.example.com/app/');

// after — server config matches the ids the bundler emitted
const MODULE_BASE = 'file:///workspace/app/'; // same root the client manifest uses
renderToPipeableStream(<App/>, MODULE_BASE);
Defensive patterns

Strategy: validation

Validate before calling

export function assertManifestInRoot(clientIds, baseURL) {
  const bad = clientIds.filter(id => !id.startsWith(baseURL));
  if (bad.length > 0) {
    throw new Error('Client modules outside baseURL ' + baseURL + ': ' + bad.join(', '));
  }
}

Type guard

export function isClientReferenceInRoot(id, baseURL) {
  return typeof id === 'string' && id.startsWith(baseURL);
}

Prevention

When it happens

Trigger: renderToPipeableStream(<App/>, baseURL) is given a baseURL that does not prefix the ids the bundler assigned to client modules: an https base while ids are file paths, a different workspace root, or a client manifest produced by another build.

Common situations: Monorepos where client and server bundles build from different roots; deploying under a new mount path; switching between file-based and URL-based module ids; stale client manifest after restructuring.

Related errors


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

Appendix: source

Thrown at packages/react-server-dom-esm/src/server/ReactFlightServerConfigESMBundler.js:51

} from '../ReactFlightESMReferences';

export function getClientReferenceKey(
  reference: ClientReference<any>,
): ClientReferenceKey {
  return reference.$$id;
}

export function resolveClientReferenceMetadata<T>(
  config: ClientManifest,
  clientReference: ClientReference<T>,
): ClientReferenceMetadata {
  const baseURL: string = config;
  const id = clientReference.$$id;
  const idx = id.lastIndexOf('#');
  const exportName = id.slice(idx + 1);
  const fullURL = id.slice(0, idx);
  if (!fullURL.startsWith(baseURL)) {
    throw new Error(
      'Attempted to load a Client Module outside the hosted root.',
    );
  }
  // Relative URL
  const modulePath = fullURL.slice(baseURL.length);
  return [modulePath, exportName];
}

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

export function getServerReferenceBoundArguments<T>(
  config: ClientManifest,
  serverReference: ServerReference<T>,

View on GitHub (pinned to eafeac097b)