If you’re building a web app with Next.js in 2025, you’ve probably come across this cryptic warning: “Warning: Only plain objects can be passed to Client Components from Server Components.” It sounds scary, right? Don’t worry—it’s a common issue, and it’s totally fixable! This guide will break down what this warning means, why it happens, and how to resolve it in a way that’s easy to understand, even if you’re new to Next.js.
Table of Contents
What Does the “Only Plain Objects” Warning Mean?
The warning pops up in Next.js when you’re trying to pass data from a Server Component to a Client Component, but the data isn’t in the right format. Specifically, Next.js expects plain JavaScript objects (like { name: "John", age: 30 }
), but you’ve passed something more complex—like a function, a class instance, or a Date object.
Why Does This Happen?
Next.js uses a powerful feature called the App Router (introduced in Next.js 13 and still rocking in 2025) to split your app into Server Components and Client Components. Here’s the deal:
- Server Components run on the server, fetch data, and render HTML. They’re super fast because they don’t ship JavaScript to the browser.
- Client Components run in the browser and handle interactive stuff, like button clicks or form inputs. They need to be “hydrated” with JavaScript.
When a Server Component passes data to a Client Component (via props), Next.js serializes the data into JSON. JSON only supports plain objects, arrays, strings, numbers, booleans, and null. If you try to pass something like a function or a complex object, Next.js throws the warning because it can’t serialize it properly.
A Quick Example
Imagine you have a Server Component that fetches user data and passes it to a Client Component:
// Server Component (page.js)
async function Page() {
const user = {
name: "John",
createdAt: new Date(), // Uh-oh! Date object
sayHello: () => "Hello!" // Uh-oh! Function
};
return <ClientComponent user={user} />;
}
// Client Component (ClientComponent.js)
'use client';
export default function ClientComponent({ user }) {
return <div>{user.name}</div>;
}
Here, new Date()
and sayHello
aren’t plain objects. When Next.js tries to serialize user
to pass it to the Client Component, it freaks out and shows the warning.
Why Should You Care About This Warning?
You might think, “It’s just a warning, not an error—can’t I ignore it?” Well, not really. Here’s why this matters:
- Broken Features: Non-serializable data (like functions) might not work in the Client Component, causing bugs.
- Performance Issues: Complex objects can slow down your app or cause hydration errors.
- Bad User Experience: If the Client Component doesn’t render correctly, your users might see glitches.
- SEO Impact: Errors in rendering can hurt your site’s search engine rankings, especially if Google can’t crawl your pages properly.
Fixing this warning makes your app faster, more reliable, and SEO-friendly—win-win!
Common Causes of the “Only Plain Objects” Warning
Let’s look at the most common reasons this warning shows up in Next.js apps:
- Passing Date Objects
JavaScriptDate
objects aren’t JSON-serializable. For example,{ createdAt: new Date() }
will trigger the warning. - Passing Functions or Methods
Functions, like() => console.log("Hi")
, can’t be serialized because JSON doesn’t support executable code. - Passing Class Instances
If you pass an instance of a class (likenew User()
), it’s not a plain object and will cause the warning. - Passing Complex Data Structures
Things likeMap
,Set
, or custom objects with circular references can’t be serialized easily. - Third-Party Library Issues
Some libraries return complex objects (e.g., MongoDB’sObjectId
or Prisma’s model instances) that aren’t plain objects.
How to Fix the “Only Plain Objects” Warning
Now that you know why the warning happens, let’s fix it! Here are step-by-step solutions for the most common scenarios, complete with code examples.
Solution 1: Convert Non-Serializable Data to Plain Objects
The easiest fix is to transform your data into a plain object before passing it to the Client Component. Here’s how:
Example: Fixing a Date Object
// Server Component (page.js)
async function Page() {
const user = {
name: "John",
createdAt: new Date().toISOString(), // Convert Date to string
};
return <ClientComponent user={user} />;
}
// Client Component (ClientComponent.js)
'use client';
export default function ClientComponent({ user }) {
return <div>{user.name} joined on {user.createdAt}</div>;
}
By converting new Date()
to a string with toISOString()
, the data becomes JSON-serializable, and the warning disappears.
Example: Removing Functions
// Server Component (page.js)
async function Page() {
const user = {
name: "John",
// No functions here!
};
return <ClientComponent user={user} />;
}
If the Client Component needs logic, move the function to the Client Component itself:
// Client Component (ClientComponent.js)
'use client';
export default function ClientComponent({ user }) {
const sayHello = () => "Hello!";
return <div>{user.name} says {sayHello()}</div>;
}
Solution 2: Handle Complex Objects from APIs or Databases
If you’re fetching data from an API or database (like MongoDB or Prisma), the returned objects might include non-serializable fields. You need to “clean” the data first.
Example: Cleaning MongoDB Data
MongoDB’s ObjectId
and Date
fields often cause issues. Here’s how to fix it:
// Server Component (page.js)
import { MongoClient } from 'mongodb';
async function Page() {
const client = await MongoClient.connect('mongodb://localhost:27017');
const db = client.db('mydb');
const rawUser = await db.collection('users').findOne({ name: "John" });
// Convert to plain object
const user = {
name: rawUser.name,
createdAt: rawUser.createdAt.toISOString(), // Convert Date
id: rawUser._id.toString(), // Convert ObjectId to string
};
return <ClientComponent user={user} />;
}
For Prisma, you can use JSON.parse(JSON.stringify(data))
as a quick fix, but be careful—it’s not always the most efficient:
// Server Component (page.js)
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function Page() {
const rawUser = await prisma.user.findFirst();
const user = JSON.parse(JSON.stringify(rawUser)); // Converts to plain object
return <ClientComponent user={user} />;
}
Solution 3: Move Logic to Client Components
If your Server Component is trying to pass functions or complex logic, consider moving that logic to the Client Component. Server Components are meant for fetching data and rendering static content, while Client Components handle interactivity.
Example: Moving Event Handlers
// Server Component (page.js)
async function Page() {
const user = { name: "John" };
return <ClientComponent user={user} />;
}
// Client Component (ClientComponent.js)
'use client';
export default function ClientComponent({ user }) {
const handleClick = () => alert(`Hi, ${user.name}!`);
return <button onClick={handleClick}>Say Hi</button>;
}
Solution 4: Use use
Hook for Client-Side Data Fetching
If you need complex data in a Client Component, you can fetch it directly in the Client Component using the use
hook (available in Next.js 13+). This avoids passing non-serializable data altogether.
// Server Component (page.js)
async function Page() {
return <ClientComponent />;
}
// Client Component (ClientComponent.js)
'use client';
import { use } from 'react';
async function fetchUser() {
const res = await fetch('/api/user');
return res.json();
}
export default function ClientComponent() {
const user = use(fetchUser());
return <div>{user.name}</div>;
}
Solution 5: Use a Serialization Library
For advanced cases, you can use libraries like superjson
to handle complex data types. superjson
serializes things like Date
, Map
, and Set
into a format that Next.js can handle.
Example: Using superjson
// Server Component (page.js)
import superjson from 'superjson';
async function Page() {
const user = {
name: "John",
createdAt: new Date(),
};
const serializedUser = superjson.stringify(user);
return <ClientComponent serializedUser={serializedUser} />;
}
// Client Component (ClientComponent.js)
'use client';
import superjson from 'superjson';
export default function ClientComponent({ serializedUser }) {
const user = superjson.parse(serializedUser);
return <div>{user.name} joined on {user.createdAt.toString()}</div>;
}
Note: Install superjson
with npm install superjson
and ensure it’s compatible with your Next.js version.
Best Practices to Avoid the Warning
To keep your Next.js app warning-free, follow these best practices:
- Always Use Plain Objects for Props
Before passing props from a Server Component, double-check that they’re plain objects or arrays. Use tools likeJSON.stringify()
to test serializability. - Keep Server Components Lean
Server Components should focus on fetching data and rendering static content. Move interactivity (like event handlers) to Client Components. - Clean API/Database Data
Always transform API or database responses into plain objects before passing them to Client Components. - Use TypeScript for Safety
TypeScript can help catch non-serializable props at compile time. Define interfaces for your props to ensure they’re plain objects. - Test Hydration
After fixing the warning, test your app to ensure Client Components hydrate correctly. Use Next.js’s dev mode (npm run dev
) to spot issues.
Debugging the Warning
If you’re still seeing the warning, here’s how to track down the culprit:
- Check the Stack Trace
The warning usually includes a stack trace in your terminal or browser console. Look for the file and line number where the prop is being passed. - Log the Props
Addconsole.log(props)
in your Client Component to inspect what’s being passed. Look for non-serializable types like functions or Dates. - Simplify the Data
Temporarily simplify the props being passed (e.g.,{ name: "Test" }
) to isolate the issue. - Use Next.js Dev Tools
Next.js’s development mode highlights hydration errors and warnings. Runnpm run dev
and check the console.
SEO Benefits of Fixing This Warning
Fixing the “Only plain objects” warning isn’t just about clean code—it’s also great for SEO! Here’s why:
- Faster Page Loads: Properly serialized props mean smoother hydration, which improves your site’s Core Web Vitals (like LCP and FCP).
- Better Crawling: Googlebot loves error-free pages. Fixing this warning ensures your pages render correctly for search engines.
- Improved User Experience: A bug-free app keeps users on your site longer, reducing bounce rates and boosting rankings.
To maximize SEO, also:
- Use descriptive
<title>
and<meta>
tags with your focus keyword (“Next.js only plain objects warning”). - Add internal links to related pages (e.g., a guide on Next.js Server Components).
- Optimize images with
next/image
for faster load times.
FAQs About the “Only Plain Objects” Warning
What is a plain object in JavaScript?
A plain object is a simple key-value structure, like { name: "John", age: 30 }
. It doesn’t include functions, Dates, or complex types like Map
or Set
.
Can I ignore this warning?
Not recommended! It can cause hydration errors, broken features, or performance issues in your Next.js app.
Does this warning only happen in Next.js?
Yes, it’s specific to Next.js’s App Router, which splits components into Server and Client Components and requires JSON-serializable props.
How do I know if my props are serializable?
Test them with JSON.stringify(props)
. If it throws an error, your props aren’t serializable.
Conclusion: Master Next.js with Confidence
The “Only plain objects can be passed to Client Components from Server Components” warning might seem intimidating, but it’s a sign that you’re diving into the exciting world of Next.js’s App Router! By understanding why this warning happens and following the solutions above, you can build faster, more reliable, and SEO-friendly web apps in 2025.
Whether you’re converting Dates to strings, cleaning database data, or moving logic to Client Components, these fixes will make your Next.js apps shine. So, go ahead—squash that warning, test your app, and keep exploring the awesome possibilities of Next.js!
Resources
- Stack Overflow: Only Plain Objects Warning – Community answers to this warning.
- Next.js Documentation – Official guide to Server and Client Components.
- Vercel Blog – Stay updated on Next.js best practices.