Alex Voznesenski
Alex Voznesenski

Reputation: 51

Cannot query field "x" on type "y"

I need some help with a Graphql query :). I'm trying to deploy the portfolio website to the Netlify and during deploy, I get this error. My code working on localhost but not on a Netlify. I need to pull data from the Contentful and populate image gallery with it.

Expected result: Netlify deploy my code

The result I got: Build error.

There was an error in your GraphQL query:
2:51:25 AM: Cannot query field "tags" on type "ContentfulArt".
2:51:25 AM: If you don't expect "tags" to exist on the type "ContentfulArt" it is most likely a typo.
However, if you expect "tags" to exist there are a couple of solutions to common problems:
2:51:25 AM: - If you added a new data source and/or changed something inside gatsby-node.js/gatsby-config.js, please try a restart of your development server
2:51:25 AM: - The field might be accessible in another subfield, please try your query in GraphiQL and use the GraphiQL explorer to see which fields you can query and what shape they have
2:51:25 AM: - You want to optionally use your field "tags" and right now it is not used anywhere. Therefore Gatsby can't infer the type and add it to the GraphQL schema. A quick fix is to add at least one entry with that field ("dummy content")
2:51:25 AM: It is recommended to explicitly type your GraphQL schema if you want to use optional fields. This way you don't have to add the mentioned "dummy content". Visit our docs to learn how you can define the schema for "ContentfulArt":
https://www.gatsbyjs.org/docs/schema-customization/#creating-type-definitions

Gatsby-node.js file

enter code here
 const path = require('path')

module.exports.createPages = async ({graphql, actions}) => {
  const { createPage } = actions
  const portfolioTemplate = path.resolve('./src/templates/gallerylist.js')
  const { data }  = await graphql(
    `
  query{
    allContentfulArt{
    edges{
      node{
        title
        tags
        publishedDate(formatString:"MMMM Do, YYYY")
        image{
          file{
              url
              }
          }
      }
    }
    }
}
`
)
//error handling


//amount of images per page = 8
  const imgPerPage = 8
  const numPages = Math.ceil(data.allContentfulArt.edges.length / imgPerPage)
//we calculate math ceiling from the total amount of objects in our query by edges.length then divide it by 8.

//we create page for each index in Numpages, ignoring the callback with "_,", path = path where we will create pages
//component - template that contain the endpoints for our create page code
//context - information to pass down into the created page
  Array.from({length:numPages}).forEach((_, i) => {
    actions.createPage({
      path: i === 0 ? `/portfolio/${1}` : `/portfolio/${i + 1}`,
      component:portfolioTemplate,
      context: {
        limit: imgPerPage,
        skip: i * imgPerPage,
        numPages,
        currentPage: i + 1
      }
    })
  })

}

My template file

import React from 'react'
import {graphql} from 'gatsby'

import Zoom from 'react-medium-image-zoom'
import Footer from '../components/footer'
import Header from '../components/header'
import Head from '../components/head'
import 'react-medium-image-zoom/dist/styles.css'
import Pagination from '../components/pagination'

import portfolioStyles from '../pages/portfolio.module.scss'


const GalleryList = ({ pageContext, data}) => {
    const {currentPage, numPages} = pageContext
    const isFirst = currentPage === 1
    const isLast = currentPage === numPages
    /*if prev page equals to currentpage -1 we return return to the first page, otherwise we go down 1 page*/ 
    const prevPage = currentPage - 1 === 1 ? `/portfolio/${1}` : `/portfolio/${currentPage - 1}`
    /*next page = currentpage + 1*/ 
    const nextPage = `/portfolio/${currentPage + 1}`


/* this will return a div container that conain gallery page 
we are passing data via different predefined constants and variables
*/
    return (
        <div className={portfolioStyles.maincontainergallery}>
            <Head title="Gallery" />

            <div className={portfolioStyles.headercomponent}>
            <Header />
            {/* Header container that includes menu and a pagination */}
            <div className={portfolioStyles.portfoliopagepaginationcontainer}>
                {/* This is pagination component with passed down props to manage the pagination */}
        <Pagination 
        isFirst={isFirst}
        isLast={isLast}
        prevPage={prevPage}
        nextPage={nextPage}/>
            </div>
            </div>

            {/* This is a gallery div container that receives data from Graphql query*/}
        <div className={portfolioStyles.portfoliopagegallerycontainer}>
        <div className={portfolioStyles.portfoliopagegallery}>
            {
            data.allContentfulArt.edges.map((edge) => {
                return (
                //we grabbing data from Contenful API using Graphql query 
                //Zoom allows us to click-zoom the images passed down from Contenftul API
                <figure  className={portfolioStyles.portfoliopagegalleryfigure} >
                
                <h3 >
                <figcaption>
                {edge.node.title}
                </figcaption>
                </h3>

                <p>{edge.node.tags}</p>

                <p>{edge.node.publishedDate}</p>
                <Zoom>
                <img src={edge.node.image.file.url} width="250" alt={edge.node.title}/>
                </Zoom>
                
                </figure>
                
                    
                )
            })
        }
        </div>
        

        
        </div>

        
        {/* this is a footer container with a footer component */}
        <div className={portfolioStyles.portfoliopagefootercontainer}>
            <Footer />
            </div>
        </div>
    )
}
/* This is graphql query to grab the code from a Contentful API */
export const pageQuery = graphql`
query($skip: Int!, $limit: Int!){
    allContentfulArt(skip: $skip, limit: $limit){
        edges{
        node{
            title
            tags
            publishedDate(formatString:"MMMM Do, YYYY")
            image{
                file{
                    url
                    }
                }
            }  
        }
        }
}`

export default GalleryList

Upvotes: 4

Views: 9712

Answers (2)

coreyward
coreyward

Reputation: 80041

First, make sure you have an instance of tags in your data.

From the documentation:

There are currently some things to keep in mind when building your content models at Contentful.

  1. At the moment, fields that do not have at least one populated instance will not be created in the GraphQL schema.
  2. When using reference fields, be aware that this source plugin will automatically create the reverse reference. You do not need to create references on both content types.

This is what your error message was trying to convey with this message:

You want to optionally use your field "tags" and right now it is not used anywhere. Therefore Gatsby can't infer the type and add it to the GraphQL schema. A quick fix is to add at least one entry with that field ("dummy content"). It is recommended to explicitly type your GraphQL schema if you want to use optional fields. This way you don't have to add the mentioned "dummy content". Visit our docs to learn how you can define the schema for "ContentfulArt"

Second, make sure that tags are available.

If you are using the preview API to pull drafts in development, it's plausible that you haven't published the content that has tags set in Contentful. When you deploy to production and pull from the non-preview API, your draft content wouldn't be available.

Finally, confirm that you have configured your environment variables in Netlify to include your Contentful access token.

Upvotes: 0

Ferran Buireu
Ferran Buireu

Reputation: 29320

This is because your Contentful schema allContentfulArt has defined a tags field as a string and, by default, can't be nullable. It always expects a result to be filled, at least for one contentfulArt.

The ideal solution is to customize your schema by adding a type definition

One easy thing you can do temporarily to bypass the issue is to add a value for your tags field or to add a white space value and trim it before, once your data is fetched.

Upvotes: 1

Related Questions