Next.js fallback:true causes undefined post during prerender
This is a classic issue related to a recent breaking change in Sanity's API! The problem is that the default perspective changed from raw to published in API version 2025-02-19.
Here's what's happening: Your postSlugsQuery is likely returning slugs for posts that exist as drafts but haven't been published yet. When getStaticProps then tries to fetch those posts with postQuery, it's only getting published documents (the new default), so it returns undefined for draft-only posts. Since your query wraps the result in an object { 'post': ... }, you get { post: undefined }, which passes your if (!post) check but then fails when your component tries to access post.mainImage.
The Fix
You have a few options:
Option 1: Explicitly set perspective to raw (Quick fix)
Update your sanityClient configuration or queries to use perspective=raw:
// If using @sanity/client
const sanityClient = createClient({
// ... your config
perspective: 'raw', // Add this
useCdn: false, // Important: CDN doesn't support raw perspective
})Or set it per query:
const { post } = await sanityClient.fetch(postQuery, { slug }, { perspective: 'raw' })Option 2: Use previewDrafts perspective (Better for preview scenarios)
If you want to see drafts overlaid on published content:
perspective: 'previewDrafts'Option 3: Filter for published documents only (Production-ready)
Update your postSlugsQuery to only return published posts:
export const postSlugsQuery = groq`
*[_type == "post" && defined(slug.current) && !(_id in path("drafts.**"))][].slug.current
`Additional Fixes
Your postQuery has an unnecessary object wrapper that's causing the undefined check to not work properly. Simplify it:
export const postQuery = groq`
*[_type == "post" && slug.current == $slug] | order(_updatedAt desc)[0] {
${postFields}
}
`Then update your fetch:
const post = await sanityClient.fetch(postQuery, { slug })This way, post will actually be null when not found, and your if (!post) check will work correctly.
Why This Happened
According to the API version 2025-02-19 documentation, Sanity changed the default perspective to published to support Content Releases. If you didn't explicitly set an API version, your client may have automatically upgraded to this version, causing draft documents to suddenly disappear from your queries.
The "ghost post" you're seeing is likely a draft document that shows up in your paths but doesn't exist in the published dataset!
Show original thread9 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.