Sanity preview "Not authenticated" error with Next.js

3 replies
Last updated: Aug 27, 2022
Suddenly I'm no longer able to preview pages with Sanity and Nextjs."Not authenticated - preview not available", from next-sanity/dist/next-sanity.esm.js:190

When in Chrome I get a flash of the page before it reverts to a 404.

Anyone else experiencing something similar today?
AI Update

I see you're hitting the "Not authenticated - preview not available" error with Next.js and Sanity. This is a common issue with Draft Mode and Visual Editing, and that flash of content before the 404 is a key clue about what's happening.

What's Causing This

The error typically stems from cookie-based authentication failing in Next.js Draft Mode. According to the Draft Mode troubleshooting documentation, when your Sanity Studio and Next.js site are on different domains (or even different subdomains), browsers can block the third-party cookies that Draft Mode relies on for authentication. The flash you're seeing is the page briefly loading before the authentication check fails and redirects to a 404.

Solutions to Try

1. Check Your Draft Mode API Route

Make sure you have a Draft Mode enable route set up. For Next.js App Router, create app/api/draft-mode/enable/route.ts:

import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const slug = searchParams.get('slug')
  
  (await draftMode()).enable()
  redirect(slug || '/')
}

2. Configure Your Presentation Tool

In your sanity.config.ts, the Presentation tool needs to point to your draft mode endpoint:

import { presentationTool } from 'sanity/presentation'

export default defineConfig({
  plugins: [
    presentationTool({
      previewUrl: {
        previewMode: {
          enable: '/api/draft-mode/enable',
        },
      },
    }),
  ],
})

3. Verify Your Authentication Token

Check that your SANITY_API_READ_TOKEN environment variable is:

  • Set correctly in your .env.local file (for local development)
  • Configured in your hosting platform's environment variables (for production)
  • Has the proper read permissions in your Sanity project settings

According to the Visual Editing with Next.js guide, when you use defineLive from next-sanity/live, you configure tokens like this:

import { defineLive } from 'next-sanity/live'
import { client } from './client'

export const { sanityFetch, SanityLive } = defineLive({
  client,
  browserToken: process.env.NEXT_PUBLIC_SANITY_API_READ_TOKEN,
  serverToken: process.env.SANITY_API_READ_TOKEN,
})

4. Check CORS Configuration

If your Studio and frontend are on different domains, ensure CORS is properly configured:

  1. Go to your Sanity project settings (Manage → API → CORS Origins)
  2. Add your frontend URL (including localhost for development)
  3. Enable "Allow credentials"

The Draft Mode troubleshooting docs mention that if browsers block third-party cookies, you may need to provide explicit token and EventSource props to subscription hooks as a workaround.

Why This Started "Suddenly"

If this just started happening today, possible causes include:

  • Token expiration or revocation - check if your API token was recently regenerated
  • Environment variable issues - recent deployment that didn't properly load env vars
  • Browser update - Chrome periodically tightens cookie policies
  • Domain changes - any recent changes to your hosting setup or URLs

Try checking your browser console for additional error messages and verify your token is valid in your Sanity project settings. If you recently deployed, double-check that all environment variables made it to your hosting platform correctly.

Show original thread
3 replies
Hi, I'm from the Ecosystem team at Sanity and am currently working on a new API for our
next-sanity
preview mode. The error is common in browsers that block third-party cookies. To solve it you'll have to provide a
token
and
EventSource
props to the subscription hook.
When in Chrome I get a flash of the page before it reverts to a 404.
Not sure about this one could you send me a preview link on dm?
Great news. I like the improvements in new-preview-mode
Hi Lasse, it's been a while but revisiting this thread (and thanks for the preview link in my DMs) I just realised I've seen this problem before. With your setup (assuming its based on what we have in our docs and starters) which uses slugs in the preview link here's why the flash happens. There are 3 steps/requests in this flow and yours if failing on the last step:1. When you first open the link it
sets the signed cookie that before redirecting you to Next.js.2. Next.js is now in Preview Mode, and what that means is that it bypasses the previously statically generated content and it'll call your
getStaticProps
similar to how it works in
next dev
. And in this mode you're giving
@sanity/client
a token, giving it access to query drafts. We recommend this pattern because it avoids a flash of published content before
@sanity/groq-store
loads up and loads your draft docs, overlaying/merging them with the published content.3.
@sanity/groq-store
doesn't have access to the token that were used in
getStaticProps
. It relies on cookie based authentication which is known to fail when: a. your studio and next site are hosted on different domains, this is usually when chrome fails.
b. if you're using a browser that agressively blocks cookies, then you also get the same warning.
4. Because it's throwing an error in addition to logging the warning it can create a uncaught error causing next to jump out of preview mode and reload the page, giving you a 404.
Now, the warning isn't very useful as it doesn't tell you what to do and is easy to miss. Leaving you unsure when, exactly, preview mode is on or off. The fact that it usually always works for the SSR stuff and you can browse your drafts just fine if you disable JavaScript, makes it even more confusing.
We're trying to address these things in the PR above. You don't have to use the experimental preview mode to fix your issue though. You can solve it almost the same way as the example in the PR.
Step 1: Add the token you use in
previewClient
to the Next.js preview data, by calling
res.setPreviewData({token})
.Step 2:
Retrieve the token from the
previewData
prop that is available on
getStaticProps
.Step 3: Return the token the
same way you pass
initialData
Step 4: Pass the token, and an instance of
EventSource
, as props to your
usePreviewSubscription
hook.
This should solve the flash of drafts before 404 issue. Please note that importing
EventSource
in your posts page is very costly and while it's only actually used in preview mode it fails to be properly dead code eliminated. Thus until we have a new preview mode out that solves this, it might be a good idea to have preview mode on different URLs/pages so that your visitors, that won't even know you have a preview mode, don't have to download all that JS.

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.

Was this answer helpful?