facebook/react · error · Error

31

31

Error message

Objects are not valid as a React child (found: ${childString === '[object Object]' ? 'object with keys {' + Object.keys(node).join(', ') + '}' : childString}). If you meant to render a collection of children, use an array instead.

What it means

Fizz's renderNodeDestructive accepts strings, numbers, arrays, iterables, React elements, thenables, and contexts as children. A plain object reaches the final branch and throws error code 31; the message reports Object.prototype.toString of the value and, for plain objects, lists its keys.

Source

Thrown at packages/react-server/src/ReactFizzServer.js:3726

        childIndex,
      );
      return result;
    }

    if (maybeUsable.$$typeof === REACT_CONTEXT_TYPE) {
      const context: ReactContext<ReactNodeList> = maybeUsable as any;
      return renderNodeDestructive(
        request,
        task,
        readContext(context),
        childIndex,
      );
    }

    // $FlowFixMe[method-unbinding]
    const childString = Object.prototype.toString.call(node);

    throw new Error(
      `Objects are not valid as a React child (found: ${
        childString === '[object Object]'
          ? 'object with keys {' + Object.keys(node).join(', ') + '}'
          : childString
      }). ` +
        'If you meant to render a collection of children, use an array ' +
        'instead.',
    );
  }

  if (typeof node === 'string') {
    const segment = task.blockedSegment;
    if (segment === null) {
      // We assume a text node doesn't have a representation in the replay set,
      // since it can't postpone. If it does, it'll be left unmatched and error.
    } else {
      segment.lastPushedText = pushTextInstance(
        segment.chunks,

View on GitHub (pinned to eafeac097b)

Solutions

  1. Convert objects to primitives before rendering: toISOString(), String(...), Array.from(...), or JSON.stringify(...)
  2. Render collections as arrays: Object.entries(obj).map(([k, v]) => ...)
  3. Pass objects as props to child components instead of rendering them as children

Example fix

// before
<div>{new Date(post.createdAt)}</div> // renders '[object Date]' branch -> throws

// after
<div>{new Date(post.createdAt).toISOString()}</div>
Defensive patterns

Strategy: validation

Validate before calling

function assertRenderableChildren(node) {
  if (node == null || typeof node === 'string' || typeof node === 'number' || typeof node === 'boolean') return;
  if (Array.isArray(node)) return node.forEach(assertRenderableChildren);
  if (typeof node === 'object' && node.$$typeof != null) return; // React element
  throw new TypeError('Objects are not valid as a React child: ' + Object.prototype.toString.call(node));
}

Type guard

function isRenderableChild(node) {
  return (
    node == null ||
    typeof node === 'string' ||
    typeof node === 'number' ||
    typeof node === 'boolean' ||
    Array.isArray(node) ||
    (typeof node === 'object' && node.$$typeof != null)
  );
}

Prevention

When it happens

Trigger: Rendering {config}, new Date(), a Map or Set, an Error instance, an ORM row, or any class instance directly as a JSX child during SSR.

Common situations: Passing server data straight into JSX (API objects, i18n bundles, URLSearchParams); forgetting toISOString()/toString()/join(); children props that unexpectedly contain an object.

Related errors


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