99designs/gqlgen

Support for nested selection sets on _FieldSet (on @requires annotation)

bartcpostma opened this issue ยท 12 comments

What happened?

We started using federation for our graphql solution. In our setup we have two graphql services, one providing items, another extending the item with breadcrumb information. In order to be able to resolve the breadcrumb information we need the id of a nested type on Item, i.e., the Variant of the Item.

According to the apollo federation specifications on the Scalar _FieldSet, it supports nested selection sets as in "variant { id }" (https://www.apollographql.com/docs/apollo-server/federation/federation-spec/#scalar-_fieldset). This does not seem to be supported by gqlgen.

I observed that gqlgen is parsing the @requires annotation argument as being 4 fields, i.e., variant, {, id and } thereby ignoring that variant has a nested selection set defined. gqlgen execution crashes at some point with:
federation: federation.gotpl: template: federation.gotpl:53:50: executing "federation.gotpl" at <.TypeReference.UnmarshalFunc>: error calling UnmarshalFunc: runtime error: invalid memory address or nil pointer dereference%

What did you expect?

That gqlgen generation works for a federation setup when having the schema setup as below.

Minimal graphql.schema

service 1:

type Item @key(fields: "id") {
     id: ID!
     variant: Variant
}
type Variant {
     id: ID!
}

service 2:

extend type Item @key(fields: "id") {
     id: ID! @external
     variant: Variant @external 
     breadcrumbs: [String!]! @requires(field: "variant { id }")
}
extend type Variant {
     id: ID! @external
}

versions

  • gqlgen version: v0.11.3
  • go version 1.13.8

I have the same issue

We have a service where we store simple entities

#Service 1
type BlogEntry  @key(fields: "id"){
   id: ID!
   date: Date!
   chapters: [Chapter]
}

type Chapter @key(fields: "id"){
    id: ID!
    category: Category!
    title: String!
    body: String
    score: Int
}


#Service 2 - extend blog entry with a recommendation. to be able to achieve this we need content from the entry 
extend type BlogEntry @key(fields: "id") {
    id: ID! @external
    chapters: [Chapter] @external
    suggestedSomethings [Something] @requires(fields: "chapters { id body }")
}

extend type Chapter @key(fields: "id"){
    id: ID! @external
    category: Category! @external
    body: String @external
}

the error is the following:

federation: federation.gotpl: template: federation.gotpl:53:50: executing "federation.gotpl" at <.TypeReference.UnmarshalFunc>: error calling UnmarshalFunc: runtime error: invalid memory address or nil pointer dereference%

stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Nope.

Hello! I'm faced with a similar situation where I need to implement a 2nd service which extends a type from another service but I'm not able to get to the error that you guys have reached. The generator is providing me with an error stating that I'm not able to use an object as a valid type. Just wondering if there's anything you did to help prevent this issue, thank you!

extend type ShoppingCart @key(fields: "items"){
    items: [Item] @external
    totalCost: Int! @requires(fields: "items { name }")
}

extend type Item @key(fields: "name") {
    name: String! @external
}

Error I'm provided failed to load schema: federation/entity.graphql:7: cannot use [Item] as argument items because OBJECT is not a valid input typeexit status 1

versions:

  • gqlgen version v0.13.0
  • go version1.16.4
oz-r commented

I'll throw my hat in here too:

Service 1

type Team @key(fields:"id"){
    id: String!
    members: [User]!
}

type User @key(fields:"id"){
    id: String!
    email: String!
}

Service 2

extend type Team @key(fields:"id"){
  id: String! @external
  members: [User]! @external
  things: [Thing!]! @requires(fields:"members { email }")
}

extend type User @key(fields:"id"){
  id: String! @external
  email: String! @external
}

I'm also seeing the same output as @bartcpostma and @pepusz

federation: federation.gotpl: template: federation.gotpl:54:51: executing "federation.gotpl" at <.TypeReference.UnmarshalFunc>: error calling UnmarshalFunc: runtime error: invalid memory address or nil pointer dereferenceexit status 1

Can some of the original commentors share how they worked around this?

Can some of the original commentors share how they worked around this?

Hello! I'm not longer working on the project as I've left my position since but I had worked around it by changing to another library instead.

After various business considerations and a pressing deadline, we favoured using another library which better supported our cases.

Apologies that this answer probably isn't as helpful as you'd hope it'd be.

@lyueyang Thanks for the reply. What was the library that you guys ended up using?

@lyueyang Thanks for the reply. What was the library that you guys ended up using?

We ended up choosing to go for the graph-gophers/graphql-go library along with the nautilus gateway.

The 99designs developers here have done a great job and this library is still great if you're looking to support Apollo's spec. However, as I was working from a clean slate, we could decide that the Apollo support was not necessary which is why we decided to go for this stack instead.

Hope this helps :)

Should be fixed with #1669. Enjoy!

Should be fixed with #1669. Enjoy!

no longer working on a project with GraphQL but nonetheless, thank you for the great work!

wow! really cool!