Juniper: Interface field resolving causes "Concrete type is not handled by instance resolvers on GraphQL union"

Created on 29 Oct 2020  ·  3Comments  ·  Source: graphql-rust/juniper

_The bug initially was found while using juniper-from-schema library. Additional information can be found in this issue. Nevertheless, I will repeat the description of the error here:_

I have some field that returns an union type:

type Query {
  testField: TestFieldResult!
}

union TestFieldResult =
  | Ok
  | SomeProblem
  | AnotherProblem

type Ok {
  dummy: Boolean!
}

SomeProblem and AnotherProblem are implementing one shared interface:

type SomeProblem implements ProblemInterface {
  message: String!
}

type AnotherProblem implements ProblemInterface {
  message: String!
}

interface ProblemInterface {
  message: String!
}

Now I'm trying to perform the query and I just need to know that there is a problem, I am not interested in a specific one:

query {
  testField {
    __typename
    ... on Ok {
      dummy
    }
    ... on ProblemInterface {
      message
    }
  }
}

And I getting an error:

thread 'actix-rt:worker:2' panicked at 'Concrete type ProblemInterface is not handled by instance resolvers on GraphQL union TestFieldResult'

However, if you specify a specific type of problem, then everything works.

Gist to reproduce an error: https://gist.github.com/acelot/0f54704452b9cff373d280ea3ee94d81

bug

Most helpful comment

@acelot examining it more deeply, seems that I was wrong. Spec has only this about spreading interfaces on unions and vice versa:

Union or interfaces fragments can be used within each other. As long as there exists at least one object type that exists in the intersection of the possible types of the scope and the spread, the spread is considered valid.

So for example

fragment unionWithInterface on Pet {
  ...dogOrHumanFragment
}

fragment dogOrHumanFragment on DogOrHuman {
  ... on Dog {
    barkVolume
  }
}

is consider valid because Dog implements interface Pet and is a member of DogOrHuman.

So, should figure out how to fix this...

All 3 comments

@acelot this is not a bug. What you want is not allowed by GraphQL spec.

Given the syntax ...on Type on GraphQL union means that you're trying to downcast the union into its variant (member). However, the spec is quite explicit about what types can represent GraphQL union variants:

  1. The member types of a Union type must all be Object base types; Scalar, Interface and Union types must not be member types of a Union. Similarly, wrapping types must not be member types of a Union.

So you cannot specify GraphQL interface in ...on Type syntax on the GraphQL union, nor you can make a GraphQL interface a variant of the union. GraphQL is not intended to work like that, sorry 🤷‍♂️

But such situation should definitely not result in a panic. Need to tune up validation rules.

it's a shame it doesn't work that way. Didn't know it was written in the spec. Strange, but other libraries support this feature like gqlgen and HotChocolate.

@acelot examining it more deeply, seems that I was wrong. Spec has only this about spreading interfaces on unions and vice versa:

Union or interfaces fragments can be used within each other. As long as there exists at least one object type that exists in the intersection of the possible types of the scope and the spread, the spread is considered valid.

So for example

fragment unionWithInterface on Pet {
  ...dogOrHumanFragment
}

fragment dogOrHumanFragment on DogOrHuman {
  ... on Dog {
    barkVolume
  }
}

is consider valid because Dog implements interface Pet and is a member of DogOrHuman.

So, should figure out how to fix this...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

takeit picture takeit  ·  5Comments

beevans picture beevans  ·  4Comments

davidpdrsn picture davidpdrsn  ·  5Comments

MikailBag picture MikailBag  ·  6Comments

librelois picture librelois  ·  3Comments