Gatsby: Single reference fields that accept multiple content types don't work in GraphQL

Created on 22 Nov 2018  路  31Comments  路  Source: gatsbyjs/gatsby

Description

Revisiting: https://github.com/gatsbyjs/gatsby/issues/3535

As stated in the previous issue (closed), single reference fields that accept multiple content types cause GraphQL to error out: "Expected value of type \"ContentfulPage\" but got: [object Object]."

The workaround is to create a multiple reference field, but this shouldn't be a permanent fix.

Steps to reproduce

Write a query for a content type with a single reference field which accepts multiple types.

GraphQL errors out.

Expected result

The field should support fragments for each content type.

Actual result

GraphQL errors out: "Expected value of type \"ContentfulPage\" but got: [object Object]."

confirmed GraphQL bug

Most helpful comment

Hi,
Any news on this?

All 31 comments

It would be great to have ready to use reproduction for this

fragment NavLink on ContentfulModelLink {
    label
    target {
      route
    }
    href {
      href
    } 
  }

When running gatsby build this fragment throws:

"Expected value of type "ContentfulPage" but got: [object Object]."

if I remove the target node, it works.

gatsby develop will go thru, but gatsby build will stop the build.

Other example. Basically I'm linking an asset to a link.

Errors:
  Expected value of type "ContentfulPage" but got: [object Object].

  GraphQL request (163:3)
  162:   label
  163:   target {
         ^
  164:     route

So I fixed this by limiting the target query to the ContentfulModelLink like this:

fragment Link on ContentfulModelLink {
    label
    ... on ContentfulModelLink {
      target {
        route
      }
      analyticsEvent
      accessibilityLabel
      additionalLabel
      tooltip
    }
    href: childContentfulModelLinkHrefTextNode {
      href
    }
    isNewWindow
  }

I wish this issue could get fixed, because it's SUPER obnoxious having to remember to unpack layout[0] in multiple places, when it should really be a single entry. Is there a reason why this isn't a priority?

@aofolts agree it sounds obnoxious! Would you like help putting together a PR to fix it?

So I was running into this issue using gatsby-source-contentful.

My content model had a Page model, which had a reference field that could be a Landing Page Layout, or a Content Page Layout.

I was trying to dynamically render the pages that had Content Page Layouts using the gatsby-node file. I was querying for allContentfulPage and I wanted to filter to only pages that had the Content Page Layout selected in the reference field. This is where I ran into the issue, because the reference field was not a union type of contentfulLandingPageLayout and contentfulContentPageLayout.

To resolve this, I moved the reference from the parent to the child object. So instead of having the reference field on the parent, I have a reference field on each of the Layout models.

Now I can query allContentfulContentPageLayouts and get all the pages that should be rendered dynamically.

This isn't ideal, but should be a good workaround until this gets resolved. The gatsby-source-contentful README.md recommends putting the reference on the child instead of the parent anyway.

@jevenson Putting the reference on the child doesn鈥檛 work in some situations, but I鈥檓 glad it resolved your issue.

  • When a child can belong to multiple parents
  • When the order of children matters (not really applicable for a single ref, but if you use this pattern elsewhere in Contentful it can be confusing to change it up)
  • When you need to impose a restriction on the number of children associated with the parent (this is true of single-assoc references: there鈥檚 no way to enforce this in Contentful when the reference is on the child)

My dirty fix is to make a one to many reference field, and then limit it to 1 entry. For some reason it works then.

{   
  allContentfulProductLandingPage{
    edges {
      node {
        name
        modules { #this is a reference type
          title
             modules { #this is a reference type
                __typename
                #title #I need title and subfields here
          }
        }
      }
    }
  }
}

How can I get more then the __typename from this query?

My content model has a page that has a reference module modules that included a title and a list of other modules. Seems that content cannot be reached with the plugin. Do you know why? and how to fix it?

@szokrika To get more than __typename you create a query for the specific types that can be in that reference field that you're trying to pull back, for example:

{   
  allContentfulProductLandingPage{
    edges {
      node {
        name
        modules { 
          title
             modules { 
                __typename
               ... on ContentfulArticleA {
                     title
               }
              ... on ContentfulArticleB {
                     title
               }
           }
        }
      }
    }
  }
}

@jrutz While that's the correct GraphQL syntax, this isn't actually supported, which is what this issue is about. See above.

@coreyward My bad, long time lurker, first time commenter on these Github threads. Meant to answer the response above me specifically given the workaround of allowing multiple references. We've run into the same issue with single references.

In case anyone will beat me to fix this - here's some places in gatsby code that are causing this:

When we produce example value to infer schema from, we select just single ___NODE value from all the nodes - this step loses information needed to correctly create Union type and we therefore we can infer just single type.

I can confirm that using one-to-many reference field, and then limiting it to 1 entry fixes this issue. Nevertheless, this is just a workaround and this issue should have top priority as it completely blocks the development.

Thanks @erickteowarang 馃帀

Hiya!

This issue has gone quiet. Spooky quiet. 馃懟

We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! 馃挭馃挏

Hi,
Any news on this?

Hi,
Any news on this?

Would be great to have this resolved.

We're also running into this, and we can confirm @stjepangolemac's confirmation that @erickteowarang's suggestion of using a one-to-many reference field limited to one reference indeed fixes the issue. However, this workaround makes me sad.

@pieh Is it possible the latest round of schema customization updates make this easier?

My dirty fix is to make a one to many reference field, and then limit it to 1 entry. For some reason it works then.

I can also confirm that this works, although not pretty.

A lot changed in #19092, but this issue isn't resolved yet.

I noticed this inconsistency too while working on #19092. Will investigate how we can fix this. I guess it won't be a breaking change as having multiple referenced types simply doesn't work now.

I've been playing around with the new type inference, trying to add a union type based on the listOfUnion type based on @pieh 's idea in https://github.com/gatsbyjs/gatsby/issues/10090#issuecomment-463023974 with some success. I don't have something working completely yet, tho.

Hey, should this issue be resolved already? Because I am experiencing the exact same problem in the moment. And the mentioned workaround https://github.com/gatsbyjs/gatsby/issues/10090#issuecomment-553634870 does not work for me either.

Any updates on this? I would appreciate it.

@LukasMachetanz No, I don't believe this has been fixed. Unfortunately @gatsbybot just closes everything that doesn't get worked on, which can lead to the false impression that it is no longer an issue.

I think you鈥檙e misunderstanding something here, the linked PR #19916 closed it and hence it should be fixed

I did run into this as well after #19916 was merged and released.

I'll set up a test repository & contentful space to check this again.

@axe312ger Do you have a reproduction for this? Because I suspect that it might be a different issue.

This is the structure I had which still caused issues ->

This was the old state, working well:

  • ContentType Page (Just a simple page with title, some text fields and so on)
  • ContentType MenuItem:

    • Title

    • Subitems (Menu items could reference sub menu items to create a menu tree)

    • Target (Single reference for page content type only)

This change broke it:

we need to add a new content type:

  • ContentType App (Like a page with some changes, irrelevant to the issue)

So we had to change the Target Field to allow referencing App content type as well.

The page was not building anymore, I don't know what error was shown, that was a while ago.

If you cant reproduce it with this, ping me, I'll try to recreate it with the original customer project :)

Thank you for clarifications!

Technically what you describe is a breaking change to the schema, so failing the query is expected. But it is unrelated to this issue.

Let me explain... Before adding App type you had:

type Page {
  id: ID!
  slug: String!
}

type MenuItem {
  target: Page
}

After you've added App it becomes:

type Page {
  id: ID!
  slug: String!
}
type App { id: ID! }

union PageAppUnion = Page | App

type MenuItem {
  target: PageAppUnion
}

Breaking changes to the schema like this must be addressed manually in your components anyways (because the structure of your data may have changed).

For example, your component that was written before this schema change could do something as simple as:

// assuming menuItem.target is always a Page type that has field "slug"
menuItem.target.slug.replace("a", "b")

After schema changes, this component will break (because when target is an App, it has no slug field).

But my main point is that it is unrelated to this issue. This issue was about the fact that the union from the last example was never created in the first place. So you couldn't even have PageAppUnion there.

I am going to close this as I am pretty sure it is fixed. And I suggest you open a new issue for your situation instead.

And strictly speaking, this was a bug in Gatsby core not in contentful source plugin.

@vladar Alright! I'll come up with a example repo as soon I come back to this. Thanks for clarification :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dustinhorton picture dustinhorton  路  3Comments

theduke picture theduke  路  3Comments

ferMartz picture ferMartz  路  3Comments

ghost picture ghost  路  3Comments

totsteps picture totsteps  路  3Comments