_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
@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:
- 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...
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:
So, should figure out how to fix this...