`client.fetch` is not a function in `resolveProductionUrl` Sanity Studio v3

2 replies
Last updated: Jun 9, 2023
Hi everyoneIm trying to generate a link to a production environment for preview in studio v3. Im using this guide
https://www.sanity.io/docs/preview-content-on-site .
But I keep getting the error:

error was thrown while trying to get your preview url: An error occurred while resolving `resolveProductionUrl`: client.fetch is not a function. (In ‘client.fetch(
*`*[_id == $postId][0].slug.current`,*
{postId: document._id}
)’, ‘client.fetch’ is undefined
My code looks like this:
productionUrl: async (prev, context) => {
      // context includes the client and other details
      const {client, dataset, document} = context

      if (document._type.includes('page')) {
        const slug = await client.fetch(
          `*[_id == $postId][0].slug.current`,
          {postId: document._id}
        )

        console.log(document._id)
        const params = new URLSearchParams()
        params.set('preview', 'true')
        params.set('dataset', dataset)

        return `<https://my-domain.com/${slug}?${params}>`
      }

      return prev
    },

AI Update

The error you're seeing happens because in Sanity Studio v3, the context object passed to productionUrl doesn't directly include a client with a fetch method. Instead, you need to use getClient() to create a client instance.

Here's the fix for your code:

productionUrl: async (prev, context) => {
  const {getClient, dataset, document} = context
  const client = getClient({ apiVersion: '2023-06-27' })

  if (document._type.includes('page')) {
    const slug = await client.fetch(
      `*[_id == $postId][0].slug.current`,
      {postId: document._id}
    )

    console.log(document._id)
    const params = new URLSearchParams()
    params.set('preview', 'true')
    params.set('dataset', dataset)

    return `https://my-domain.com/${slug}?${params}`
  }

  return prev
}

The key change: Replace const {client, dataset, document} = context with const {getClient, dataset, document} = context, then call getClient() to create your client instance.

However, there's actually a simpler approach that doesn't require fetching at all. Since the document object in the context already contains all the document's fields, you can access the slug directly:

productionUrl: async (prev, context) => {
  const {document, dataset} = context

  if (document._type.includes('page')) {
    const slug = document.slug?.current
    
    if (!slug) {
      return prev
    }

    const params = new URLSearchParams()
    params.set('preview', 'true')
    params.set('dataset', dataset)

    return `https://my-domain.com/${slug}?${params}`
  }

  return prev
}

This second approach is recommended because:

  • It's simpler and doesn't require an extra API call
  • The document data is already available in the context
  • It's faster since there's no network request

The getClient() approach is only necessary if you need to query for data that isn't on the current document (like fetching related documents or doing more complex queries).

This is a known issue that was discussed in the Sanity community, and the documentation has since been updated to reflect the correct v3 API.

Show original thread
2 replies
I think the bit of docs is outdated! Can you try:
const {getClient, dataset, document} = context

const client = getClient({ apiVersion: '2023-06-27' })
works like a charm : ) Thanks a lot!

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?