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 imported on the server are opaque client references wrapped in a Proxy. Reading any non-internal property (other than the handful of passthroughs like $$id, name, Provider) throws: the server cannot see inside a client value, it can only pass the reference through to the client. The error names the exact expression that was dot-accessed.

Source

Thrown at packages/react-server-dom-unbundled/src/ReactFlightUnbundledReferences.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. Pass the imported name through untouched (as a prop or JSX element) instead of reading properties off it.
  2. Move any metadata that the server genuinely needs into a shared module without 'use client'.
  3. Special-case logging/inspection helpers to skip objects that carry the client reference marker ($$typeof === Symbol.for('react.client.reference')).

Example fix

// before (server component)
import Button from './Button.client';
const label = Button.displayName;

// after: metadata lives in a shared server-readable module
import { BUTTON_LABEL } from './button.meta';
const label = BUTTON_LABEL;
Defensive patterns

Strategy: type-guard

Validate before calling

// Guard generic property readers
function safeProp(obj, key) {
  if (isClientReference(obj)) {
    throw new Error(`Cannot read ${String(key)} of a client reference on the server`);
  }
  return obj[key];
}

Type guard

const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
export function isClientReference(value) {
  return value != null && value.$$typeof === CLIENT_REFERENCE_TAG;
}

Prevention

When it happens

Trigger: In server code: `clientExport.someProperty`, e.g. `Button.displayName`, `mod.utils.format`, `ctx.Provider === ...` style checks on anything outside the proxy's whitelist, or spreading/inspecting a client export.

Common situations: Reading static properties off a client component (e.g. for registration catalogs or metadata) inside a server component; IDE-driven autocomplete that evaluates property access in server context; devtools or logging helpers that enumerate object properties of client references.

Related errors


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