gateway icon indicating copy to clipboard operation
gateway copied to clipboard

Error: "cannot query field "id" on type "UnionType"

Open prokaktus opened this issue 3 years ago • 3 comments

Hello!

I've met the error when using inline fragments.

Description

Schema:

type Cat {
	id: ID!
	name: String!
}

type Dog {
	id: ID!
	name: String!
}

union Animal = Cat | Dog

type Query {
	animals: [Animal!]!
}

Query:

query MyQuery {
	animals {
		... on Cat {
			id
			name
		}
		... on Dog {
			id
			name
		}
	}
}

If Dog and Cat are defined in the same location, it works well.

But if you define Dog and Cat in different locations, then first query in plans generate:

(query generated by Gateway)

{
  animals {
    ... on Cat {
      id
      name
    }
    id
  }
}

Which is invalid, because we cannot query fields on Union, except __typename. Graphql spec told so:

the following query is invalid, because the union itself defines no fields:

{
  firstSearchResult {
    name
    height
  }
}

https://spec.graphql.org/June2018/#sec-Unions

Possible workaround

Use defined fragments.

Query like this will work:

query MyQuery {
	animals {
		... on Cat {
			...CatFragment
		}
		... on Dog {
			...DogFragment
		}
	}
}

fragment CatFragment on Cat {
	id,
	name
}
fragment DogFragment on Dog {
	id,
	name
}

I'll try to provide testcase and fix for this issue.

prokaktus avatar Mar 07 '21 14:03 prokaktus

The same problem happens with query, if Dog and Cat from different locations:

query {
	animals {
		...CatFragment
		...DogFragment
	}
}

fragment CatFragment on Cat {
	id
	name
}
fragment DogFragment on Dog {
	id
	name
}

prokaktus avatar Mar 07 '21 19:03 prokaktus

Turned out this is a lot trickier to fix than I expected.

Problem is somewhere there: https://github.com/nautilus/gateway/blob/107892653e275349638cf703482d2c91573d25a3/plan.go#L389-L392

When gateway handling unions fragments, there added id field to unions SelectionSet, and this is invalid syntax for graphql.

prokaktus avatar Mar 08 '21 17:03 prokaktus

Oh, damn yea this is going to bring you very deep into the weeds of the query planning process. It sounds like you are on the right track tho! Since its safe to assume that every boundary type has ID, you should be able to just ensure that ID shows up the different conditions for the union and instead of adding it straight to the selection set.

AlecAivazis avatar Mar 08 '21 19:03 AlecAivazis