Issue with CORS when accessing dataset using @sanity/client in Gatsby app.

5 replies
Last updated: Jul 30, 2020
Morning folks! Having some issues with CORS when trying to access my dataset, specifically from the
@sanity/client.
Following the docs at
https://www.sanity.io/docs/cors and at https://www.sanity.io/docs/js-client , I've setup a small query in my Gatsby react app to retrieve some entries with
useEffect(() => {
    const client = sanityClient({
      projectId: process.env.GATSBY_SANITY_PROJECT_ID,
      dataset: process.env.GATSBY_SANITY_DATASET,
      token: process.env.SANITY_READ_TOKEN,
      useCdn: false
    })
    client.fetch(`*[_type == "portfolioEntry"]{ title }`).then(res => {
      console.log('res', res)
    }).catch(err => {
      console.error('F', err)
    })
  })
However, I receive the response

Access to XMLHttpRequest at 'https://<project-id>.<http://api.sanity.io/v1/data/query/development?query=*%5B_type%20%3D%3D%20%22portfolioEntry%22%5D%7B%20title%20%7D|api.sanity.io/v1/data/query/development?query=*%5B_type%20%3D%3D%20%22portfolioEntry%22%5D%7B%20title%20%7D>' from origin '<http://localhost:8000>' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
Following suggestions online, It said to investigate the allowed CORS origins, and so I made sure to add
https://<project-id>.<http://api.sanity.io|api.sanity.io>

Request works in both Postman and Chromium.
Thanks in advance to anyone that takes the time to give me a hand!
AI Update

I can see exactly what's causing your CORS issue! The error message about Access-Control-Allow-Credentials being empty when it should be 'true' is a telltale sign.

The problem is that when you pass a token to the Sanity client, it automatically sets withCredentials: true on requests. This requires the "Allow credentials" checkbox to be enabled in your CORS configuration.

Here's how to fix it:

  1. Go to manage.sanity.io
  2. Select your project
  3. Navigate to Settings → API → CORS Origins
  4. Add http://localhost:8000 (your Gatsby dev server)
  5. Most importantly: Check the "Allow credentials" checkbox for this origin

The origin you mentioned adding (https://<project-id>.api.sanity.io) is incorrect - that's the Sanity API itself, not your application's origin. You need to add the domain where your Gatsby app runs (http://localhost:8000 for development).

A couple other things to check:

  • Make sure your environment variables are actually loading (add a console.log to verify)
  • Your useEffect is missing a dependency array, so it's running on every render. Add [] as the second argument to run it only once:
useEffect(() => {
  const client = sanityClient({
    projectId: process.env.GATSBY_SANITY_PROJECT_ID,
    dataset: process.env.GATSBY_SANITY_DATASET,
    token: process.env.SANITY_READ_TOKEN,
    useCdn: false
  })
  client.fetch(`*[_type == "portfolioEntry"]{ title }`).then(res => {
    console.log('res', res)
  }).catch(err => {
    console.error('F', err)
  })
}, []) // <-- Add this dependency array

Why it works in Postman/Chromium: Those tools don't enforce CORS the same way browsers do with web applications, which is why you're only seeing the issue in your Gatsby app.

Once you enable "Allow credentials" for http://localhost:8000, your requests should work! When you deploy to production, remember to add your production domain with credentials enabled as well.

If you go to your project on manage.sanity.io and to Settings &gt; API &gt; CORS Origins, do you see
<http://localhost:8000>
listed as one of the entries? Also, does it have “credentials allowed” switched on in this case?
Yep!
You’d want Allow credentials to be switched on for that one, which right now is not the case - even if the lock would suggest otherwise, sorry about that 😉
😄
Thank you! What a head scratcher. I didn't add that one, it was a default, so I didn't want to mess with it. I appreciate the help!

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?