Fragments on Interface not resolving

In the GraphQL specification 2.8.1 is stated that fragments can be specified on objects, interface and unions.
Unfortunately, Dgraph do not resolve fragments for interfaces, leading to errors in the query result

interface  Meta {
  id: String! @id @search(by: [hash])
}

interface Generic {
  names: [String!]!
}

type Movie implements Meta & Generic {
  description: String!
}
query {
   getMeta(id:"NmU4YTRhODQ5") {
       ... on Generic {
           names
       }
   }
}

=>

"message": "Cannot return null for non-nullable field Movie.names.",

Hey @Luscha

Could you share the Dgraph version you are using and a small reproducible example for this? That is a small sample of your dataset?

schema:

interface  Meta {
  id: String! @id @search(by: [hash])
}

interface Generic {
  names: [Text!]!
}

type Text {
	text: String!
	localization: String!
}

type Movie implements Meta & Generic {
  description: String!
}

mutation:

mutation {
  addMovie(input: [{id : "1", description: "simple description", names: [{text:"star wars", localization:"en_US"}]}]) {
    numUids
  }
}

query:

query {
   getMeta(id:"1") {
    id
    ... on Generic {
      __typename
      names {
        text
      }
    }
   }
}

Turned out that the query do not return an error on standalone/latest, where the fragment simply do not resolve anything.
In dgraph:v20.07.2 it returns the above error.

"message": "Cannot return null for non-nullable field Movie.names."

@pawan

After further tests I figured out the actual behavior:

The fragment on interface do not resolve in dgraph, returning a null field. Putting an apollo server in front of dgraph and mirroring the schema, it expect the names to not be null (type definition) but because behind dgraph do not resolve the fragment and returns null, the apollo server triggers the error above described.

Hi @Luscha, I am not getting the above error while applying fragment on interface. I have used same schema, queries and mutations which you mentioned and tried on both v20.07.2 and master branch.

Response of query which uses fragment on interface:

Response of query which uses fragment on type that implements interface:

@JatinDevDG
The error is triggered when putting an apollo server in front of dgraph because the schema tells apollo that querying on the fragment should return names and description.

The query with the fragment on interface should resolve in the same way of the type which implements the interface (according to the GraphQL specification).

I guess interfaces are useful because you want to query things without listing all the implementing types
EG:
I have an ecommerce with a lot of “products” interface with name, image and description implemented by cloth (with size), ebook (format available), PC (with specifications) and printed book (ISBN13-10 …).

Right now to get a search result you have to query

query {
   getProduct(first:10) {
         ... on Cloth {
             name
             image
             description
         }
         ... on Ebook {
             name
             image
             description
         }
         .....
   }
} 

which simply nullyfy the benefit of having an interface

Based on your last response it’s still not clear what the problem is @Luscha. What is the GraphQL query that is failing for you? What’s the expected response for it and what are you actually getting?

You don’t have to list all the types that implement the interface. You only have to list them if you want to get a field that is not part of the interface. So the query below should also work for you, as long as the name, description, and image are fields in the interface definition.

query {
   getProduct(first:10) {
         name
         image
         description
   }
} 

Hi @Luscha, we find out the query below should work when getMeta returns an object of a type that implements both Meta and Generic. Otherwise, it should return an error.We are not getting this behaviour right now. So, we are accepting this bug and will have a fix soon. Thanks.

query {
   getMeta(id:"1") {
    id
    ... on Generic {
      __typename
      names {
        text
      }
    }
   }
}

@pawan
Sorry, I got confused as well trying to explain the problem:

Conditions:
Type A implements interface B and C

Action:

query {
   getB {
   ... on C {
         some C Fields
      }
   }
}

Expected behavior:
The fragment on C should resolve for A because it implements the 2 interfaces

Actual Behaviour:
The fragment do not resolve and some C Fields is not returned for object A.
This behavior is worsened if an apollo server is used as gateway, because it expects the fields to be returned (schema definition) and triggers an error to the client, failing the query

@Luscha
Yeah, we should get the expected behaviour as you mentioned. We will investigate this issue and fix it soon.

1 Like

Hi @Luscha, we have solved this bug and the fix is currently added in the master branch and will also be available in the 20.11 release.

PR: https://github.com/dgraph-io/dgraph/pull/6964

Thank you! It will make life mush simpler <3

1 Like