Image Serializer Error: Works on Navigation but Fails on Direct Link
This is a classic Next.js serialization issue! The error "Cannot stringify a function image" occurs because you're likely passing your Portable Text serializers/components through Next.js data-fetching methods like getStaticProps or getServerSideProps, which can only return JSON-serializable data.
The Problem:
When you navigate within your app (client-side routing), the serializers work fine because they're already loaded in the browser as JavaScript functions. But when you access the page directly via URL (server-side rendering), Next.js tries to serialize the props returned from getStaticProps/getServerSideProps, and functions (like your image serializer) cannot be serialized to JSON.
The Solution:
Move your Portable Text component configuration to the client-side component rather than passing it through your data-fetching functions. Here's how:
❌ Don't do this:
// pages/noticias/[slug].js
export async function getStaticProps({ params }) {
const post = await client.fetch(query, { slug: params.slug })
return {
props: {
post,
components: { // ❌ Can't serialize functions!
types: {
image: MyImageComponent
}
}
}
}
}✅ Do this instead:
// pages/noticias/[slug].js
import { PortableText } from '@portabletext/react'
import imageUrlBuilder from '@sanity/image-url'
const builder = imageUrlBuilder(client)
// Define components in the component file, not in getStaticProps
const components = {
types: {
image: ({ value }) => (
<img
src={builder.image(value).url()}
alt={value.alt || ''}
/>
)
}
}
export default function NoticiaPage({ post }) {
return (
<article>
<PortableText
value={post.body}
components={components} // ✅ Defined client-side
/>
</article>
)
}
export async function getStaticProps({ params }) {
const post = await client.fetch(query, { slug: params.slug })
return {
props: {
post // ✅ Only serializable data
}
}
}Key Points:
- Only pass plain data (strings, numbers, arrays, objects) through
getStaticProps/getServerSideProps - Define your Portable Text components/serializers in your React component, not in the props
- The image data from Sanity (references, URLs, etc.) is serializable—it's the component functions that aren't
If you're using the older block-content-to-react or custom serializers, the same principle applies: keep the serializer functions in your component code, not in your data-fetching returns.
This is a Next.js limitation - the devalue library they use for serialization cannot handle functions, which is why you see this error specifically on direct page loads but not on client-side navigation.
Show original thread11 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.