Troubleshooting a groq query with a reference in Sanity.io

26 replies
Last updated: Nov 12, 2021
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
hey nice to see you’re using Next now! Re: difference between vision & code, check for these:• Are you querying against the same API version? (e.g.
v1
vs.
2021-03-25
)• Same dataset?
• On vision, drafts can show up in query results while on the frontend you’d need to set a API token for the Sanity client. Are you looking at the same document on both vision & your frontend?
• I'm pretty sure the api is the same but how can I check? My sanity config is using a date I set a few weeks ago• Same dataset definitely
• All the documents are published so they shouldn't be drafts
Thanks for the reply
user G
sorry it took me awhile to respond, had some bigger issues I had to jump on instead 😓
I confirmed the version is
2021-10-29
but how can I confirm this is the same API version I'm querying against?
If that’s what’s returned from
client
, that’s the version of the API it’s using when it queries.
If you mean the version you’re querying against in Vision, that’s set via the dropdown in the top-left. You can choose Other and then enter
2021-10-29
to match them identically.
If I’ve misunderstood please let me know.
If that’s what’s returned from
client
, that’s the version of the API it’s using when it queries.
If you mean the version you’re querying against in Vision, that’s set via the dropdown in the top-left. You can choose Other and then enter
2021-10-29
to match them identically.
If I’ve misunderstood please let me know.
No that sounds right Geoff but I'm not sure it ultimately helps me solve the original problem
Thanks for the reply of course
My reference expands in Vision, but not in my code when I
console.log()
the returned data
You’re right—it doesn’t. That said, now that we know it’s not a version issue, we can take a look back at the original issue.
What are you seeing returned from that query on your front end?
So regarding the data mismatch between the code and Vision, I get this when I run the query in Vision:
But I get this in the code (note the key is the same, but it's missing the 'slug' parameter)
user A
apologies for the delayed response
I tried a whole other query just to see if I could get the results another way. Again this works in Vision but not in the code itself;
    *[_type == "page" && slug.current == $slug] {
      blocks[_type match 'sectionMarker']{'slug': link->slug.current, ...},
      ...
    }
Is there any way of looking up/resolving a
_ref
using JavaScript instead of groq? Something like
resolveRef(_ref)
which would return a slug or something?
Is there any way of looking up/resolving a
_ref
using JavaScript instead of groq? Something like
resolveRef(_ref)
which would return a slug or something?
Further details on this... I realised that my API version in 'Vision' was set to 'v1' — I just set it to 'v2021-03-25' and now the query above isn't working. So
user A
and
user G
were correct, it WAS an API version issue (sorry both!) ...
The question now is what is the correct query?
Further details on this... I realised that my API version in 'Vision' was set to 'v1' — I just set it to 'v2021-03-25' and now the query above isn't working. So
user A
and
user G
were correct, it WAS an API version issue (sorry both!) ...
The question now is what is the correct query?
Got it 😂 what a rollercoaster...

    *[_type == "page" && slug.current == $slug] {
      blocks[_type == 'sectionMarker'] {
        'slug': link->slug.current,
        ...
      },
      ...,
    }
Hah! Glad you got it. You can also do this to handle multiple types:
blocks[] {
  ...,
  _type == "sectionMarker" => {
    "slug": link->slug.current,
  },
  _type == "somethingElse" => { ... }
}
edit: added missing
[]
Yeah that's neater, thanks Derek
I had to change it to
blocks[] {
but it worked
ah oops my bad — thanks for correcting that!
No problem! Easy for me when I can test it
No problem! Easy for me when I can test it
Hey, no problem! Glad you got it resolved in the end, and thanks (again) Derek for the support.

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?