next.js

"Only plain objects" error when fetching MongoDB/Mongoose data from Server Component


I'm working with Next.js 15.2.0 App Router and encountering a consistent error message in my terminal. I have a Server Component that fetches a Property document from my MongoDB database.

When running the application, I repeatedly get the following error messages in the console when I visit this particular page:

Only plain objects can be passed to Client Components from Server Components. Objects with toJSON methods are not supported. Convert it manually to a simple value before passing it to props. {{_id: {buffer: ...}}

Server component


interface PropertyPageProps {
  params: { id: string };
}

export default async function PropertyPage({ params }: PropertyPageProps) {
  const { id } = params;

  // Fetch the property from MongoDB using Mongoose
  const dbProperty = await PropertyModel.findById(id)

  if (!dbProperty) {
    return <div>Property not found.</div>;
  }

  return (
    <main>
      <h1>Property Page</h1>
      <PropertyDetailsClient property={dbProperty} />
    </main>
  );
}

Client component

'use client';

interface PropertyDetailsClientProps {
  property: {
    _id: string; 
    // ... other properties ...
  };
}

export default function PropertyDetailsClient({ property }: PropertyDetailsClientProps) {
  return (
    <div className="property-details">
      <h2>{property.name}</h2>
      <p>ID: {property._id}</p>
      <p>Created At: {new Date(property.createdAt).toLocaleDateString()}</p>
    </div>
  );
}

The page is working correctly, but the message doesn't go away and it only happens for this page where I fetch the data on server component.

Am I doing something wrong? And how can I get ride of this message?

I've tried checking for rules of fetching db data on Next.js component, but nothing.


Solution

  • When you're pulling data straight from your database within a Server Component and want to send it over to a Client Component, You need to serialise it to turn it into a simple, readable format for the client component.

    A common way to do this is by using JSON.parse(JSON.stringify(data))

    const property = JSON.parse(JSON.stringify(dbProperty))
    <PropertyDetailsClient property={property} />
    

    This flattens the complex database object into something the client component can easily understand.