User encounters empty result due to Incognito mode in Sanity query

4 replies
Last updated: Mar 18, 2025
Hi Sanity Supports. I have an app that makes a v1 query withCredential set to true. I can see from the devTools that the sanitySession cookie was included with the request. The user that is logged in is with Contributor role. However I got a response with empty result. while if I ran the same query in Vision, I got a result.
// response
{
    "query": "*[\n    _type == \"post\"\n    \u0026\u0026 slug.current == $slug\n    \u0026\u0026 _id in path(\"drafts.**\")\n  ] | order(_updatedAt desc)[0] {\n  _id,\n  title,\n  slug,\n  body,\n  authors[]-\u003e    \n}",
    "result": {},
    "ms": 2
}

// payload
query: *[
    _type == "post"
    && slug.current == $slug
    && _id in path("drafts.**")
  ] | order(_updatedAt desc)[0] {
  _id,
  title,
  slug,
  body,
  authors[]->    
}
$slug: "here-s-a-2nd-draft"
AI Update

I can see your issue! You're querying for drafts using the v1 API with credentials, but there are a few important things to understand about how draft access works in Sanity.

The Problem: API Endpoint and Perspective

When you use withCredentials: true with the v1 API, you're sending the sanitySession cookie, which is correct for authenticated requests. However, there are several factors that could cause your query to return empty results even though it works in Vision.

Key Issues to Check:

1. Are you using the CDN endpoint?

When querying drafts, you must use the non-CDN endpoint (api.sanity.io), not the CDN endpoint (apicdn.sanity.io). The CDN is optimized for published content and doesn't serve draft documents. Make sure useCdn: false in your client configuration.

2. Missing perspective parameter

The v1 API doesn't automatically know you want to query drafts. You should explicitly set perspective=previewDrafts in your API request. This tells Sanity to prioritize draft documents over published ones.

3. API version default perspective change

If you're using a recent API version (specifically 2025-02-19 or later), be aware that the default perspective changed from raw to published. This means without explicitly setting the perspective, you'll only get published documents, which could explain your empty result.

The Solution

Here's how to fix your configuration:

// Make sure you're using the non-CDN client
const client = createClient({
  projectId: 'your-project-id',
  dataset: 'your-dataset',
  useCdn: false, // Critical: must be false for drafts
  apiVersion: '2024-01-01', // or your preferred version
  token: 'your-token', // Recommended for programmatic access
  perspective: 'previewDrafts', // This prioritizes drafts
  withCredentials: true // If using cookie-based auth
})

If you're making direct HTTP requests, ensure you're adding the perspective as a query parameter:

https://[PROJECT_ID].api.sanity.io/v1/data/query/[DATASET]?query=...&perspective=previewDrafts

Why Vision Works But Your App Doesn't

Vision (the query tool in Sanity Studio) automatically uses the correct API endpoint with proper authentication context and perspective settings. It's configured to access drafts by default when you're logged in, which is why your query works there but not in your app.

Understanding Perspectives

According to the perspectives documentation, there are several perspectives available:

  • raw - Returns all documents including both drafts and published
  • published - Returns only published documents (now the default in newer API versions)
  • previewDrafts - Prioritizes draft documents over published versions when both exist (ideal for your use case)

Since your query explicitly filters for _id in path("drafts.**"), you're only looking for draft documents. Without the proper perspective set, the API might not return these documents even with valid credentials.

Verify Your Setup

Double-check these items:

  1. βœ… useCdn: false in your client configuration
  2. βœ… perspective: 'previewDrafts' is set
  3. βœ… The user has appropriate permissions (Contributor role should work)
  4. βœ… The draft document actually exists with the slug you're querying
  5. βœ… You're using the api.sanity.io endpoint, not apicdn.sanity.io

The combination of using the CDN endpoint or missing the perspective parameter is the most common reason for this issue. Setting perspective=previewDrafts with useCdn: false should resolve your empty result problem.

Oh never mind, I was running in Incognito mode. :p
should I just delete this thread?
No, you can keep it in case some one else runs into the same issue πŸ˜„
hi
user J
, this same exact request when ran in Safari. It never included a request cookie, so it always returned empty results. Here's the server response header:
:status: 200
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: <http://localhost:3000>
Access-Control-Expose-Headers: Content-Type, Content-Length, ETag, X-Sanity-Deprecated, X-Sanity-Warning, X-Sanity-Shard
Access-Control-Max-Age: 600
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding: gzip
Content-Length: 193
Content-Type: application/json; charset=utf-8
Date: Tue, 18 Mar 2025 16:12:40 GMT
ratelimit-limit: 500
ratelimit-remaining: 499
ratelimit-reset: 1
sanity-gateway: k8s-gcp-us-w1-prod-ing-01
sanity-query-hash: XP0VgQc4D5U c51eYPQvYkc
Server-Timing: api;dur=7
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Vary: Accept-Encoding, origin
Via: 1.1 google
x-ratelimit-limit-second: 500
x-ratelimit-remaining-second: 499
x-sanity-shard: gcp-eu-w1-prod-40009
x-served-by: gradient-query-5fcf9b7b9f-rxs4z
do you know if we need to do some extra for Safari to honor withCredentials:true?

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?