apollographql / apollographql/federation
Query returns incorrect data when there is a conflict between query field alias and entity key field
- Dominant language
- TypeScript
- Stars
- 725
- Forks
- 276
- Avg merge
- 1h 47m
- Merged PRs (30d)
- 1
Description
### Issue Description
When a query aliases a field on a fetched entity to the same name as the key of the entity, the server starts to return the wrong data if the query is modified to include fields joined from multiple subgraphs. That's a bit wordy, but I'll break up the reproduction sample here.
Subgraph one defines the entity as:
```
type Query {
object: O
}
type O @key(fields: "id") {
id: ID!
legacyId: ID
a: String
}
```
Then we have a rather simple query here, which uses the legacyId and not the id that is the entity's key. The legacyId is aliased to `id` which matches the entity's key.
```
query TestQuery {
object {
id: legacyId
legacyId # Not necessary but used later to focus attention to the issue
a
}
}
```
At this point, everything is fine. Given the following resolver:
```
resolvers: {
Query: {
object() {
return { __typename: 'O', id: 'newId', legacyId: 'legacyId', a: 'a' };
},
},
},
```
We end up with the expected result:
```
{
"object": {
"a": "a",
"id": "legacyId",
"legacyId": "legacyId",
},
}
```
Notice id and legacyId are the same (because id is just an alias).
When we introduce a second subgraph that extends this entity, complications arise.
```
extend type O @key(fields: "id") {
id: ID!
a: String @external
b: String @requires(fields: "a")
}
```
Modifying our test query to include the new field `b`:
```
query TestQuery {
object {
id: legacyId
legacyId # Not necessary but used later to focus attention to the issue
a
}
}
```
Results in the unexpected:
```
{
"object": {
"a": "a",
"b": "B: a",
"id": "newId",
"legacyId": "legacyId",
},
}
```
`id` and `legacy` no longer match, instead `id` is replaced with the actual `id` field and the alias is now longer functioning.
### Link to Reproduction
https://github.com/apollographql/federation/pull/3035
### Reproduction Steps
_No response_
Contributor guide
Research direction
Start with the reproduction linked in pull request #3035, using the two subgraph schemas, resolver, and aliased TestQuery described here. Compare the single-subgraph and extended-entity responses, focusing on the conflicting id alias; done means the alias remains legacyId while the joined field b is resolved correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100