Understanding and troubleshooting GROQ queries, getStaticProps, and getStaticPaths in Next.js

7 replies
Last updated: Mar 12, 2023
This request:`const query = groq`*[_type == "release" && slug.current == $slug][0]`
Gives me this error response:

{"error":{"description":"param $slug referenced, but not provided","end":44,"query":
What am I doing wrong?
Mar 11, 2023, 9:31 PM
Try change it to this:

const $slug = '/mySlug'

const query = `*[_type == "release" && slug.current == "${slug}"][0]
Where you set $slug to the slug you want to get.
Mar 11, 2023, 9:45 PM
I'm really confused about all the references in the groq query and getStaticProps and getStaticPaths..
`const query = groq`*[_type == "release" && release.catalog_number == $slug][0]`
Type is ok. but after the &&, the first one is the property from the groq that I want the slug to be set from right? And after the second == the $ references a variable by this name outside the groq query? Am I getting it right?
Mar 11, 2023, 10:52 PM
..and then when you get to getStaticProps, you need the params from the getStaticPaths query? Just to let getStaticProps know which document you are fetching right? ..and then, the client.fetch .... the first parameter is simple, but the second one? Does it tell the query what document to get? Why/how? I don't get it..
Mar 11, 2023, 10:58 PM
Here's a working example from my practice project. This is using SSR though but it should be easy enough to modify it to use static props:

export const getServerSideProps: GetServerSideProps  = async (pageContext: GetServerSidePropsContext) => {
  const pageSlug: string | string[] | undefined = pageContext.query.slug

  if (!pageSlug) {
    return {
      notFound: true

  // eslint-disable-next-line @typescript-eslint/typedef
  const query = `*[_type == 'post' && slug.current == "${pageSlug}"] {
    author-> {
    "mainImageDimensions": mainImage.asset->metadata.dimensions,
    "mainImageUrl": mainImage.asset->url,

  try {
    const post: PostType[] = await sanityClient.fetch(query)

    if (!post || post.length === 0) {
      return {
        notFound: true

    return {
      props: {
        post: post[0]
  } catch (error) {
    return {
      notFound: true
Mar 11, 2023, 11:02 PM
user U
first argument in sanity client
method takes the GROQ query. In your example,

const query = groq`*[_type == "release" && slug.current == $slug][0]

here will be replaced with 2nd parameter you pass in.

sanityClient.fetch(query, { slug })
For example, if the
has a value of

Then the query above will be translated to:

*[_type == "release" && slug.current == 'post-1'][0]
Mar 12, 2023, 2:27 PM
And the slug here:
sanityClient.fetch(query, { slug })
..comes from getStaticPaths and exported params? Or?
Mar 12, 2023, 11:16 PM
Why does it have {}?
Mar 12, 2023, 11:16 PM

Sanity– build remarkable experiences at scale

The Sanity Composable Content Cloud is the headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?