facebook/react · error · Error
Only plain objects, and a few built-ins, can be passed to Se
Error message
Only plain objects, and a few built-ins, can be passed to Server Functions. Classes or null prototypes are not supported.
What it means
encodeReply's object branch accepts plain objects and specific built-ins; before accepting a value it checks the prototype chain. If getPrototypeOf(value) is neither Object.prototype nor a supported built-in prototype - i.e. class instances and null-prototype objects - and no temporaryReferences set was passed to stash them, serialization throws with this message. The point is that class identity does not survive the wire, so React refuses rather than silently downgrading your instance to a plain object.
Source
Thrown at packages/react-client/src/ReactFlightReplyClient.js:742
const getAsyncIterator: void | (() => $AsyncIterator<any, any, any>) = (
value as any
)[ASYNC_ITERATOR];
if (typeof getAsyncIterator === 'function') {
// We treat AsyncIterables as a Fragment and as such we might need to key them.
return serializeAsyncIterable(
value as any,
getAsyncIterator.call(value as any),
);
}
// Verify that this is a simple plain object.
const proto = getPrototypeOf(value);
if (
proto !== ObjectPrototype &&
(proto === null || getPrototypeOf(proto) !== null)
) {
if (temporaryReferences === undefined) {
throw new Error(
'Only plain objects, and a few built-ins, can be passed to Server Functions. ' +
'Classes or null prototypes are not supported.' +
(__DEV__ ? describeObjectForErrorMessage(parent, key) : ''),
);
}
// We will have written this object to the temporary reference set above
// so we can replace it with a marker to refer to this slot later.
return serializeTemporaryReferenceMarker();
}
if (__DEV__) {
if ((value as any).$$typeof === REACT_CONTEXT_TYPE) {
console.error(
'React Context Providers cannot be passed to Server Functions from the Client.%s',
describeObjectForErrorMessage(parent, key),
);
} else if (objectName(value) !== 'Object') {
console.error(
'Only plain objects can be passed to Server Functions from the Client. ' +View on GitHub (pinned to eafeac097b)
Solutions
- Convert to a plain object before the call: {...instance} (spread drops the prototype and methods) or a toJSON()/toPlain() mapper
- Rebuild null-prototype objects as normal object literals
- If the server must see the actual instance, pass a TemporaryReferenceSet via options so the object is stored and referred to by id
- Prefer sending identifiers (IDs) and rehydrating the entity server-side
Example fix
// before
class Cart { constructor(items) { this.items = items; } total() {...} }
await saveCart(new Cart(items)); // throws
// after
await saveCart({items: [...items]}); // plain object literal
// or: await saveCart({...cartInstance}); Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the argument tree before calling the server
import {isPlainObjectOrArray} from './guards'; // typeGuard below
function assertReplySerializable(v: unknown, seen = new Set()): void {
if (v === null || typeof v !== 'object' || seen.has(v)) return;
seen.add(v);
if (v instanceof Map || v instanceof Set || v instanceof Date) return; // built-ins OK
if (!isPlainObjectOrArray(v)) {
throw new Error(`Non-plain object (${v.constructor?.name}) cannot be sent to a Server Function`);
}
Object.values(v).forEach(c => assertReplySerializable(c, seen));
} Type guard
const isPlainObjectOrArray = (v: unknown): v is Record<string, unknown> | unknown[] => {
if (typeof v !== 'object' || v === null) return false;
const proto = Object.getPrototypeOf(v);
return proto === Object.prototype || proto === Array.prototype;
}; Prevention
- Convert instances to plain objects ({...instance} or a mapper) at the boundary
- Type server-function parameter types as plain serializable structures
- Send IDs and rehydrate entities server-side
- Add a dev-mode assertReplySerializable pass over args in your action wrapper
When it happens
Trigger: Passing new MyClass(...) (including instances of imported library classes), Object.create(null) objects, or framework/state-library objects as Server Function arguments without a temporaryReferences option; the check fires even when the class is defined in shared code, because instances are not serializable by value.
Common situations: Sending form-state objects created by class-based stores; passing ORM/model or domain entities; structured-clone-style objects with null prototypes produced by libraries; migrating fetch bodies to Server Function args without converting shapes.
Related errors
- Missing a temporary reference set but the RSC response retur
- React Element cannot be passed to Server Functions from the
- Client Functions cannot be passed directly to Server Functio
- Symbols cannot be passed to a Server Function without a temp
- Type ${typeof value} is not supported as an argument to a Se
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/4aaeacc8b0f90a85.
Report an issue: GitHub.