Resolve Next.js Server Component serialization errors. Understand Server vs Client boundaries and how to pass state across RSC borders.
A Server Component attempted to pass a non-serializable function or event handler (such as `onClick` or `onChange`) across the boundary into a Client Component. Server Component props must be JSON-serializable to support streaming HTML over the network.
Next.js Server Components serialize props into the Flight protocol stream. Functions cannot be serialized across network boundaries; interactive event listeners must be defined directly inside Client Components annotated with `"use client"`.
// Server Component (app/page.tsx) - FAILS
export default function Page() {
const handleClick = () => console.log('clicked');
return <ClientButton onClick={handleClick} />;
}// Solution: Define interaction inside the Client Component
// components/ClientButton.tsx
'use client';
export function ClientButton() {
const handleClick = () => console.log('clicked');
return <button onClick={handleClick}>Click Me</button>;
}Resolution Note: Move event handlers into the Client Component rather than passing them from Server Components.
Verify the file defining the interactive event handler has the `"use client";` directive at line 1.
Check if server actions (`"use server";`) should be used if the intent is to trigger backend mutations.
Ensure all props passed from Server to Client Components are JSON serializable (no functions, Symbols, or class instances).
Prevent recurrence by enforcing this verification check in staging or pre-commit hooks:
import nextPlugin from '@next/eslint-plugin-next';
export default [
{
plugins: { '@next/next': nextPlugin },
rules: {
...nextPlugin.configs.recommended.rules,
},
},
];