facebook/react · error · Error

Cannot access ${expression} on the server. You cannot dot in

Error message

Cannot access ${expression} on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.

What it means

Named exports of a 'use client' module are server-side Proxies (deepProxyHandlers) that expose only a whitelist: Flight metadata ($$typeof/$$id/$$async/name), displayName/defaultProps/_debugInfo/toJSON returning undefined, Symbol.toPrimitive/Symbol.toStringTag, and Context.Provider. Reading any other property throws with the exact 'Name.prop' expression, because the property's value would only exist in the browser where the module actually runs.

Source

Thrown at packages/react-server-dom-webpack/src/ReactFlightWebpackReferences.js:197

        // $FlowFixMe[prop-missing]
        return Object.prototype[Symbol.toPrimitive];
      case Symbol.toStringTag:
        // $FlowFixMe[prop-missing]
        return Object.prototype[Symbol.toStringTag];
      case 'Provider':
        // Context.Provider === Context in React, so return the same reference.
        // This allows server components to render <ClientContext.Provider>
        // which will be serialized and executed on the client.
        return receiver;
      case 'then':
        throw new Error(
          `Cannot await or return from a thenable. ` +
            `You cannot await a client module from a server component.`,
        );
    }
    // eslint-disable-next-line react-internal/safe-string-coercion
    const expression = String(target.name) + '.' + String(name);
    throw new Error(
      `Cannot access ${expression} on the server. ` +
        'You cannot dot into a client module from a server component. ' +
        'You can only pass the imported name through.',
    );
  },
  set: function () {
    throw new Error('Cannot assign to a client module from a server module.');
  },
};

function getReference(target: Function, name: string | symbol): $FlowFixMe {
  switch (name) {
    // These names are read by the Flight runtime if you end up using the exports object.
    case '$$typeof':
      return target.$$typeof;
    case '$$id':
      return target.$$id;
    case '$$async':

View on GitHub (pinned to eafeac097b)

Solutions

  1. Import the deeper name directly: import {Chart} from './charts' instead of import * as Charts plus Charts.Chart.COLORS
  2. Expose what you need as additional named exports of the client module and import those
  3. Move shared constants/objects out of the 'use client' file into a directive-free shared module
  4. Do not pass client references to HOC or statics-reading utilities on the server

Example fix

// before (server component)
import * as Charts from './charts'; // 'use client'
const COLORS = Charts.Chart.COLORS; // dots into a client export -> throws

// after
// colors.js (no 'use client'): export const COLORS = [...]
import {COLORS} from './colors';
import {Chart} from './charts';
Defensive patterns

Strategy: type-guard

Validate before calling

function safeRead(obj, key) {
  if (isClientReference(obj)) {
    // Only metadata and component usage are allowed; do not dot into it.
    return undefined;
  }
  return obj[key];
}

Type guard

const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');

function isClientReference(value) {
  return (
    value !== null &&
    (typeof value === 'object' || typeof value === 'function') &&
    value.$$typeof === CLIENT_REFERENCE_TAG
  );
}

Try / catch

try {
  value = clientExport.prop;
} catch (e) {
  if (String(e.message).includes('on the server') && String(e.message).includes('Cannot access')) {
    value = undefined; // pass the reference through instead of reading into it
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Dotting into a client export instead of importing the deeper name: Charts.Chart.COLORS, Icon.paths, Button.metadata. HOC, prop-type, or statics-reading machinery touching non-whitelisted properties of a client component reference. Debug tooling or console expansion that evaluates getters on the proxy.

Common situations: Component libraries re-exported through 'use client' barrels whose config objects or sub-objects are read by wrapper code; namespace-style access (import * as X then X.export.prop); devtools inspection of client references during SSR debugging.

Related errors


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