Reference expansion works in Vision but not in Next.js code

26 replies
Last updated: Jan 28, 2026
Good morning everyone. I have a groq query with a reference that works in the 'vision' tab, but not in my code for some reason;
  *[_type == "page" && slug.current == 'values-and-beliefs'] {
    blocks[] {"slug": link->slug.current, ...},
    ...
  }

link
here is a
reference
and I'm trying to expand it out. In Vision, I can see a new field called
slug
with the value of whatever the reference is (
about
,
news
, etc), but in my code I don't see the same field
Using Next
AI Update

This is a classic issue with perspectives and draft documents in Sanity! Based on similar cases in the community, here's what's happening:

The Problem: Vision Shows Drafts by Default

The Vision plugin in Sanity Studio queries with a different default perspective than your client code. Vision typically shows you draft documents (documents with IDs prefixed by drafts.), while your client code by default only queries published documents.

When you dereference with the -> operator (like link->slug.current), Vision successfully resolves the reference because it can see the draft document. But your client code can't see that draft, so the dereferencing fails silently and you don't get the slug field.

The Solution: Align Your Perspectives

You have a few options:

1. Publish Your Documents (Simplest)

Make sure the documents you're referencing are actually published (not just drafts). In Studio, click the "Publish" button on any draft documents. This is what happened in the community thread I found - the generalSettings document had _id: "drafts.us-generalSettings" which wasn't visible to the unauthenticated client.

2. Use an Authenticated Client with Token (For Preview Mode)

If you need to see drafts in your application (like for preview functionality), configure your client with a read token and use the previewDrafts perspective:

import {createClient} from '@sanity/client'

const client = createClient({
  projectId: 'your-project-id',
  dataset: 'production',
  apiVersion: '2024-01-01',
  useCdn: false,
  token: process.env.SANITY_API_READ_TOKEN, // Required for drafts
  perspective: 'previewDrafts', // This prioritizes drafts over published
})

3. Check Your API Version Perspective Default

As of the 2025-02-19 API version, the default perspective changed to published (previously raw). Make sure you're explicitly setting the perspective you want:

const result = await client.fetch(query, params, {
  perspective: 'published' // or 'previewDrafts' for preview mode
})

Why This Happens

The reference access operator (->) internally executes a subquery to fetch the referenced document. If that document only exists as a draft (ID: drafts.your-doc-id) and your client is querying with the published perspective, the reference resolves to null, and you won't see any fields from it.

Quick Diagnostic

Run this query in both Vision and your client to see what's being returned:

*[_type == "page" && slug.current == 'values-and-beliefs'][0] {
  blocks[] {
    _type,
    "linkRef": link._ref,
    "linkResolved": link->{_id, slug}
  }
}

If Vision shows the resolved data but your client doesn't, you've confirmed it's a perspective/draft issue. Look for any _id fields starting with drafts. - those are your culprits!

Show original thread
26 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.

Was this answer helpful?