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.

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)

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.