gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.19k stars 10.33k forks source link

"Cannot return null for non-nullable" for ".id" in definedTypes #21201

Closed a-rbsn closed 4 years ago

a-rbsn commented 4 years ago

I'll preface this by saying everything has been working fine up until this point and I am using gatsby-source-prismic for this website.

The errors I am getting coincide with types that have been defined in gatsby-node.js as seen below — when I run gatsby develop or gatsby build I receive an error for each of my defined types that says: Cannot return null for non-nullable field PrismicProjectData.id. — but according to the docs we don't need to explicitly define id, parent etc:

Note that you don’t need to explicitly provide the Node interface fields (id, parent, etc.), Gatsby will automatically add them for you.

Even when I do define id under the types it still reproduces the same set of errors.

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    type PrismicStudioInformationBodyImageFieldPrimary implements Node {
      image_caption: String
    }
    type PrismicContactInformationData implements Node {
      twitter: String
      instagram: String
      email_address: String
    }
    type PrismicProjectBodyImagePrimary implements Node {
      image_caption: String
    }
    type PrismicProjectBodyTwoImagesPrimary implements Node {
      left_image_caption: String
      right_image_caption: String
    }
    type PrismicProjectData implements Node {
      project_location: String
      featured_image_caption: String
    }
  `
  createTypes(typeDefs)
}

The errors that are occurring:

There was an error in your GraphQL query:

Cannot return null for non-nullable field PrismicContactInformationData.id.

The field "PrismicContactInformationData.id." was explicitly defined as non-nullable via the schema customization API (by yourself or a plugin/theme). This means that this field is not optional and you have to define a value. If this is not your desired behavior and you defined the schema yourself, go to "createTypes" in gatsby-node.js. If you're using a plugin/theme, you can learn more here on how to fix field types:
https://www.gatsbyjs.org/docs/schema-customization/#fixing-field-types

   3 |   aspectRatio
   4 |   src
   5 |   srcSet
   6 |   sizes
   7 | }
   8 |
   9 | query usersarSitesfromworksFinalsrccomponentsjournalJs1412619347 {
  10 |   prismicContactInformation {
  11 |     id
  12 |     data {
> 13 |       id
     |       ^
  14 |       instagram
  15 |     }
  16 |   }
  17 |   allInstaNode(sort: {fields: timestamp, order: DESC}) {
  18 |     edges {
  19 |       node {
  20 |         id
  21 |         localFile {
  22 |           id
  23 |           childImageSharp {

File path: /Users/ar/Sites/fromworks-final/src/components/journal.js
Plugin: none
  System:
    OS: macOS 10.15.2
    CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
    Shell: 5.7.1 - /usr/local/bin/zsh
  Binaries:
    Node: 10.15.3 - /usr/local/bin/node
    Yarn: 1.15.2 - ~/.nvm/versions/node/v11.12.0/bin/yarn
    npm: 6.4.1 - /usr/local/bin/npm
  Languages:
    Python: 2.7.16 - /usr/bin/python
  Browsers:
    Chrome: 79.0.3945.130
    Safari: 13.0.4
  npmPackages:
    gatsby: ^2.19.12 => 2.19.12 
    gatsby-image: ^2.2.40 => 2.2.40 
    gatsby-plugin-emotion: ^4.1.22 => 4.1.22 
    gatsby-plugin-manifest: ^2.2.41 => 2.2.41 
    gatsby-plugin-offline: ^3.0.34 => 3.0.34 
    gatsby-plugin-react-helmet: ^3.1.22 => 3.1.22 
    gatsby-plugin-react-svg: ^2.1.2 => 2.1.2 
    gatsby-plugin-sharp: ^2.4.5 => 2.4.5 
    gatsby-plugin-web-font-loader: ^1.0.4 => 1.0.4 
    gatsby-source-filesystem: ^2.1.48 => 2.1.48 
    gatsby-source-instagram: ^0.5.1 => 0.5.1 
    gatsby-source-prismic: ^2.3.0-alpha.3 => 2.3.0-alpha.3 
    gatsby-transformer-json: ^2.2.26 => 2.2.26 
    gatsby-transformer-remark: ^2.6.50 => 2.6.50 
    gatsby-transformer-sharp: ^2.3.14 => 2.3.14 
Js-Brecht commented 4 years ago

At first glance, it looks to me like prismicContactInformation is the Node, and not PrismicContactInformationData. Am I wrong in that assumption? Is the data field of prismicContactInformation a foreign key?

If PrismicContactInformationData is simply a data field that gets attached to prismicContactInformation, then you probably don't need implements Node in the type definition.

I haven't really done a thorough examination, though. You will know better than me how your data is being structured.

Js-Brecht commented 4 years ago

After a cursory examination of gatsby-source-prismic, it looks like the data field becomes a container of (potential) nodes, but I don't think it becomes a node itself. So, I can see how defining it as implements Node could cause an error.

a-rbsn commented 4 years ago

@Js-Brecht — thank-you very much for your fast response and correct solution.

Turns out removing implements Node fixed the issue, but it's funny how it worked before. I guess something updated and this needed amending.

So learning point for me — implements Node is only for higher level types?

As for your first question, I believe gatsby-source-prismic puts all of the data into these Data types, which means within the source you refer to the normal type, but if something needs inferring it's using the Data type? Kind of confusing but it seems to be working.

Js-Brecht commented 4 years ago

yes implements Node would be your root nodes. That's the only piece that needs the ID, and other internal types.

gatsby-source-prismic has a type of "normalization" process that it does on the data container. Based on the type of the data in the fields within that data container, it performs various operations, converting fields of certain types to their respective nodes, and converting the field itself into a foreign key.

So, for something like an image field, I believe it would create an image type. That will make a brand new root node by creating a new file node, and linking it to the requisite field, like this. This, I believe, would give you access to all of the ImageSharp data.

So, that would be how it infers the types, and how you can get so much extended information based on the information collected from your API.

There's several layers of, I would say, unnecessary abstraction going on in that plugin, which can make it a bit more difficult than it should be to reason about what it's doing... but we're not here to talk about my opinions 🤷‍♂

Js-Brecht commented 4 years ago

Was there any recent updates to gatsby-source-prismic? Perhaps they used to turn the data field into a root node itself? If they changed that behavior, it would (or should) have been a major update, because that is definitely a breaking change.

According to npm, last publish was a year ago

a-rbsn commented 4 years ago

@Js-Brecht — yeah just seen it's been a long time since the plugin was updated, other than that I have no idea unless it was a gatsby update that caused it.

Js-Brecht commented 4 years ago

Can't say for sure. I know they were doing some work on refactoring the GraphQL schema/processing stuff, and I think they're still working on extending it to support 3rd party schemas better. It's possible that some small change could have caused it... say, if they made the ID inferred from a Node type non-nullable instead of being inferred from the data structure itself? As unlikely as it would be that that specific behavior would have only been added recently, that would just be a way I could see it happening

Js-Brecht commented 4 years ago

Closing this issue as resolved