Intended outcome:
When using client.query()
the resulting data
is always null whenever fetchPolicy is set to cache-first
and there are missing fields from the projected result. For instance, if we're supposed to query an user like: user { uuid email picture }
and for some reason the server does not return field picture, then result will be:
// Query
client.query({
query: gql`query { user { uuid email picture } }`,
fetchPolicy: "cache-first",
}).then(r => console.log(r));
// Result
{
data: null
loading: false
networkStatus: 7
stale: true
}
In my particular case, my backend never serializes null values. Since user's picture
and many other fields are optional (nullable), we constantly face this problem.
I've also noticed we'll get a Missing field picture warning on the console. In addition, the user data will be cached and I can retrieve at client.cache.data.data
. However, not directly from the promise result.
Finally, If we change the fetchPolicy to no-cache
, the problem does not happen and we can also access the resulting data.
Actual outcome:
data
should not be null since the result is valid. In case of missing field picture
, the user data should successfully return uuid
and email
fields. An example would be:
{
"data": {
"user": {
"uuid": "72e442f7-8246-4330-9fd4-b2701fc8b93f"
"email": "[email protected]"
}
}
}
How to reproduce the issue:
Please, see query above.
Versions
System:
OS: Linux 4.15 Pop!_OS 18.04 LTS
Binaries:
Node: 11.2.0 - /usr/bin/node
npm: 6.4.1 - /usr/bin/npm
Browsers:
Chrome: 70.0.3538.110
Firefox: 63.0
npmPackages:
apollo-cache-inmemory: 1.3.11 => 1.3.11
apollo-client: 2.4.7 => 2.4.7
apollo-link: 1.2.4 => 1.2.4
apollo-link-error: 1.1.2 => 1.1.2
apollo-link-http: 1.5.7 => 1.5.7
react-apollo: 2.3.2 => 2.3.2
apollo-client works only with graphql servers that actually adhere to the graphql specification. It clearly states:
If result is null (or another internal value similar to null such as undefined or NaN), return null.
Your graphql server does not adhere to the specification. Instead of returning per spec
{
"data": {
"user": {
"uuid": "72e442f7-8246-4330-9fd4-b2701fc8b93f",
"email": "[email protected]",
"picture": null
}
}
}
you are returning
{
"data": {
"user": {
"uuid": "72e442f7-8246-4330-9fd4-b2701fc8b93f",
"email": "[email protected]"
}
}
}
So the behavior of apollo-client is undefined.
I am closing this as this works if the graphql server is behaving to spec.
Thank you for replying @danilobuerger. If that's the case, why Apollo cache the resulting data at all, but fail to return it in the promise? That's very confusing for us since I can still retrieve the results directly from cache. Also, if that's to be considered some sort of erroneous behavior, Apollo could provide some extra logs/warnings stating that to guide us into the expected way.
As I wrote: the behaviour of Apollo is undefined, if your server does not behave as per spec.
Could we have some sort of explicit warning or error messaging saying that there was some issue parsing the data instead of silently returning undefined?
It's quite common to have this sort of bug in the api especially when the data object is large so having a useful error message will go along way in terms of dev experience.
Most helpful comment
Could we have some sort of explicit warning or error messaging saying that there was some issue parsing the data instead of silently returning undefined?
It's quite common to have this sort of bug in the api especially when the data object is large so having a useful error message will go along way in terms of dev experience.