keyFields mismatch with query leads to hard Invariant Violation crash
See original GitHub issueIntended outcome:
Specifying unknown fields in keyFields
(or failing to ask for all keyFields
in queries) should result in a catchable exception which doesn’t affect the entire server process.
Actual outcome:
When I pass an unknown field name to keyFields
in InMemoryCache configuration, the entire node process crashes down with Invariant Violation
error.
Here’s the stacktrace I’m getting with the repo below:
/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/zen-observable/lib/Observable.js:65
throw e;
^
Invariant Violation: Missing field 'foo' while computing key fields
at new InvariantError (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/ts-invariant/lib/invariant.js:16:28)
at Object.invariant (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/ts-invariant/lib/invariant.js:28:15)
at /Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:3788:130
at Array.forEach (<anonymous>)
at computeKeyObject (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:3777:15)
at /Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:3740:13
at Policies.identify (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:3454:33)
at StoreWriter.processSelectionSet (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:4448:27)
at StoreWriter.processFieldValue (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:4536:21)
at /Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:4485:47
at Set.forEach (<anonymous>)
at StoreWriter.processSelectionSet (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:4471:17)
at StoreWriter.writeToStore (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:4420:29)
at InMemoryCache.write (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:4659:37)
at InMemoryCache.ApolloCache.writeQuery (/Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:3321:21)
at /Users/berekuk/coding/tmp/apollo-crash/apollo-crash/node_modules/@apollo/client/apollo-client.cjs.js:2359:31
My attempts to pin down this problem lead me to setTimeout
call in zen-observable’s hostReportError and to invariant(…) call in computeKeyObject in apollo-client.
How to reproduce the issue:
Here’s my repo which reproduces the problem: https://github.com/berekuk/bug-apollo-keyFields-crash
It uses Next.js since that’s how I discovered this issue and since I didn’t want to implement a custom Express.js server just for this bugreport.
I also tried to reproduce it with a simple node script which used apolloClient.watchQuery
but didn’t succeed. useQuery
probably does something differently, but I’m not sure what exactly.
Versions
See https://github.com/berekuk/bug-apollo-keyFields-crash/blob/master/package.json:
"@apollo/client": "^3.0.2",
"graphql": "^15.3.0",
PS: Besides this specific issue, I’d very much prefer for apollo-client never to do something like this on non-fatal errors. I’m worried, though, because it seems like apollo-client calls invariant()
quite often, and though I’m not familiar with ts-invariant and zen-observable APIs, it probably behaves like a hard non-easily-catchable assertion in all those cases (?).
Issue Analytics
- State:
- Created 3 years ago
- Reactions:13
- Comments:23 (6 by maintainers)
Top GitHub Comments
The big issue with this is how difficult it is to track down the offending query as the stack trace and message give no clue as to which one it is except for the field name.
I’m completely ok with this mistake causing an exception which I (or my framework, e.g. Next.js) would have to catch explicitly.
I’m definitely NOT ok with this error bringing my entire production website down, as it happened today 😦 One page/query which I wrote incorrectly or forgot about during a refactoring or apollo-client upgrade (it worked fine in 2.6) shouldn’t have this effect.
Actually, I believe no kind of code except for syntax errors should have this effect, and I’m really strugging to understand why it’s acceptable to intentionally write
setTimeout(() => { throw new Error() })
in any npm library.