facebook/react · error · Error

React Element cannot be passed to Server Functions from the

Error message

React Element cannot be passed to Server Functions from the Client without a temporary reference set. Pass a TemporaryReferenceSet to the options.

What it means

When serializeReply (encodeReply) walks arguments for a Server Function call, React Elements cannot be represented in the Flight reply protocol by value - they must be registered in a TemporaryReferenceSet that the server later reads back. If no temporaryReferences option was passed, there is nowhere to record the element and the serializer throws, telling you to pass a TemporaryReferenceSet in the options.

Source

Thrown at packages/react-client/src/ReactFlightReplyClient.js:440

            const parentReference = writtenObjects.get(parent);
            if (parentReference !== undefined) {
              // If the parent has a reference, we can refer to this object indirectly
              // through the property name inside that parent.
              const reference = parentReference + ':' + key;
              // Store this object so that the server can refer to it later in responses.
              writeTemporaryReference(temporaryReferences, reference, value);
              return serializeTemporaryReferenceMarker();
            }
          }
          // This element is the root of a serializeModel call (e.g. JSX
          // passed directly to encodeReply, or a promise that resolved to
          // JSX). It was already registered as a temporary reference by
          // serializeModel so we just need to emit the marker.
          if (temporaryReferences !== undefined && modelRoot === value) {
            modelRoot = null;
            return serializeTemporaryReferenceMarker();
          }
          throw new Error(
            'React Element cannot be passed to Server Functions from the Client without a ' +
              'temporary reference set. Pass a TemporaryReferenceSet to the options.' +
              (__DEV__ ? describeObjectForErrorMessage(parent, key) : ''),
          );
        }
        case REACT_LAZY_TYPE: {
          // Resolve lazy as if it wasn't here. In the future this will be encoded as a Promise.
          const lazy: LazyComponent<any, any> = value as any;
          const payload = lazy._payload;
          const init = lazy._init;
          if (formData === null) {
            // Upgrade to use FormData to allow us to stream this value.
            formData = new FormData();
          }
          pendingParts++;
          try {
            const resolvedModel = init(payload);
            // We always outline this as a separate part even though we could inline it

View on GitHub (pinned to eafeac097b)

Solutions

  1. Create a TemporaryReferenceSet and pass it: const temporaryReferences = createTemporaryReferenceSet(); await encodeReply(args, {temporaryReferences})
  2. Thread the same set to the server decoder (decodeReply(body, {temporaryReferences})) so both ends resolve the same ids
  3. Scope the set per request and reuse it for the whole round-trip; do not create a second set mid-flight
  4. If you did not mean to send elements, send serializable data (props/ids) and render the element on the server instead

Example fix

// before
await saveConfig({header: <Title>Hello</Title>}); // encodeReply throws

// after
import {createTemporaryReferenceSet} from 'react-server-dom-webpack/client';
const temporaryReferences = createTemporaryReferenceSet();
await callServer(saveConfig.$$id, [{header: <Title>Hello</Title>}], {temporaryReferences});
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check the argument tree for elements before invoking the server
const REACT_ELEMENT = Symbol.for('react.transitional.element');
function containsElement(v, seen = new Set()): boolean {
  if (v === null || typeof v !== 'object' || seen.has(v)) return false;
  seen.add(v);
  if ((v as any).$$typeof === REACT_ELEMENT) return true;
  return Object.values(v).some(c => containsElement(c, seen));
}
// usage:
if (containsElement(args)) {
  temporaryReferences = createTemporaryReferenceSet(); // will be required
}

Type guard

const REACT_ELEMENT = Symbol.for('react.transitional.element');
const isReactElement = (v: unknown): v is {$$typeof: symbol} =>
  typeof v === 'object' && v !== null &&
  (v as any).$$typeof === REACT_ELEMENT;

Prevention

When it happens

Trigger: Passing JSX or React Elements (e.g. {node: <Foo/>} or children) as arguments to a Server Function, or as the root of encodeReply, without an options object containing temporaryReferences; also elements nested deeper inside objects/arrays in the argument tree.

Common situations: Sending rendered UI snippets (rich content, slot fills) to server actions; libraries that accept ReactNode payloads from the client; hand-rolled encodeReply/decodeReply plumbing where the per-request set was not created or threaded.

Related errors


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