Originally started here: https://github.com/apollographql/react-apollo/issues/1117
When using cache-and-network and the server throws an error, the promise does not return to the executor, and it's not possible to catch and handle the error.
The actual code is here:
https://github.com/apollographql/apollo-client/blob/a1217fbd1ebe8b56ff96dcb077430720dd0b381c/src/core/QueryManager.ts#L505-L507
Intended outcome:
Promise should return, so the callee can use .catch(...) on the promise.
Actual outcome:
Return value it undefined, and the callee can't handle the error.
How to reproduce the issue:
Use catch-and-network fetch policy, and cause the server to fail the query.
Version
@dotansimha I think this is fixed in the 2.0. I'll check and see but could you send a reproduction issue for me to try out?
@jbaxleyiii
It looks like the code is the same under master branch:
https://github.com/apollographql/apollo-client/blob/master/packages/apollo-client/src/core/QueryManager.ts#L363
So if the promise does not return from the function, the callee can't handle a rejection.
To see a running example with the error, clone this: https://github.com/dotansimha/apollo-client-unhandled-expection , under the cache-and-network directory.
Run yarn and yarn start.
The executed query uses cache-and-network policy, using watchQuery, and the next callback prints to log, and error callback prints the error with a custom text.
You will notice that the error is thrown from the resolver (sever-side), and the client unable to handle it. The error is first caught with the custom error handler, and then the original callee of the query can't catch it, and it causing an unhandled promise rejection.
{ data: undefined, loading: true, networkStatus: 1, stale: true }
error caught: { Error: GraphQL error: oops
at new ApolloError (/Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:1981:28)
at /Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3091:41
at /Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3583:25
at Array.forEach (<anonymous>)
at /Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3580:27
at Array.forEach (<anonymous>)
at QueryManager.broadcastQueries (/Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3577:42)
at /Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3512:31
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
graphQLErrors:
[ { Error: oops
at posts (/Users/dotansimha/Dev/temp3/index.js:47:13)
at resolveFieldValueOrError (/Users/dotansimha/Dev/temp3/node_modules/graphql/execution/execute.js:498:12)
at resolveField (/Users/dotansimha/Dev/temp3/node_modules/graphql/execution/execute.js:462:16)
at /Users/dotansimha/Dev/temp3/node_modules/graphql/execution/execute.js:311:18
at Array.reduce (<anonymous>)
at executeFields (/Users/dotansimha/Dev/temp3/node_modules/graphql/execution/execute.js:308:42)
at executeOperation (/Users/dotansimha/Dev/temp3/node_modules/graphql/execution/execute.js:236:122)
at executeImpl (/Users/dotansimha/Dev/temp3/node_modules/graphql/execution/execute.js:133:26)
at execute (/Users/dotansimha/Dev/temp3/node_modules/graphql/execution/execute.js:110:229)
at InBrowserNetworkInterface.query (/Users/dotansimha/Dev/temp3/index.js:88:12) message: 'oops', locations: undefined, path: [Array] } ],
networkError: null,
message: 'GraphQL error: oops',
extraInfo: undefined }
(node:2926) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: GraphQL error: oops
(node:2926) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(Note the UnhandledPromiseRejectionWarning)
When removing the cachePolicy line, the custom error handler can catch it, and the custom error handler prints:
error caught: { Error: GraphQL error: oops
at new ApolloError (/Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:1981:28)
at /Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3091:41
at /Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3583:25
at Array.forEach (<anonymous>)
at /Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3580:27
at Array.forEach (<anonymous>)
at QueryManager.broadcastQueries (/Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3577:42)
at /Users/dotansimha/Dev/temp3/node_modules/apollo-client/apollo.umd.js:3512:31
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
This issue is very similar to another issue I opened: https://github.com/apollographql/apollo-client/issues/2271
It's a real pain for me because I am using react-native and unhandled promise rejection causing the app to crash.
Thanks for the reproduction! I'll take a look!
@dotansimha this was SO helpful to fix! Thank you for the excellent work! Fixed via https://github.com/apollographql/apollo-client/pull/2281
@dotansimha if you want to PR this fix into the latest branch (for the 1.any) line, you should be able to do the same thing as in this commit https://github.com/apollographql/apollo-client/pull/2281/commits/b67367c38d250e6fc1079576fa022b63f93124de. I'd be happy to merge and release it for the 1.any if needed!
Thank you @jbaxleyiii ! awesome!!!
BTW, @jbaxleyiii, I guess that we can also fix https://github.com/apollographql/apollo-client/issues/2271 with a similar solution
This still appears to be broken. cache-and-network always returns 'undefined' for data.
Most helpful comment
@jbaxleyiii
It looks like the code is the same under
masterbranch:https://github.com/apollographql/apollo-client/blob/master/packages/apollo-client/src/core/QueryManager.ts#L363
So if the promise does not return from the function, the callee can't handle a rejection.
To see a running example with the error, clone this: https://github.com/dotansimha/apollo-client-unhandled-expection , under the
cache-and-networkdirectory.Run
yarnandyarn start.The executed query uses
cache-and-networkpolicy, usingwatchQuery, and thenextcallback prints to log, anderrorcallback prints the error with a custom text.You will notice that the error is thrown from the resolver (sever-side), and the client unable to handle it. The error is first caught with the custom error handler, and then the original callee of the query can't catch it, and it causing an unhandled promise rejection.
(Note the
UnhandledPromiseRejectionWarning)When removing the
cachePolicyline, the custom error handler can catch it, and the custom error handler prints:This issue is very similar to another issue I opened: https://github.com/apollographql/apollo-client/issues/2271
It's a real pain for me because I am using
react-nativeand unhandled promise rejection causing the app to crash.