Apollo-client: Unifying error handling further

Created on 26 Jul 2016  路  10Comments  路  Source: apollographql/apollo-client

It is somewhat difficult to handle errors well at the moment. I'm using this issue to write down some ideas as to how we can improve error handling within Apollo Client.

Goals

  1. It should be easy to ignore error handling entirely and just have the errors printed to the console
  2. It should be easy to differentiate the type of error that has occurred within the set of stuff that Apollo deals with
  3. It should be easy to distinguish errors caused by application code and errors caused by stuff that Apollo Client or react-apollo deals with

    Design

As far as I can tell, there are four types of errors that can occur:

  1. GraphQL errors: errors returned as part of the response from the server
  2. Network errors: errors that occur when attempting to get a response from the server
  3. Client errors: errors that are thrown from within Apollo Client (e.g. a generated id node attempted to overwrite a real id node).
  4. Application errors: errors that are thrown from within the application code that uses Apollo Client.

We don't have to do anything to (4) other than make sure that they can be caught and handled by the application developer (or, just written to the console). There are some outstanding issues with react-apollo that affect errors of type (4).

Each of (1), (2) and (3) should be represented with an instance of ApolloError. Instances of the type ApolloError will now have the following properties:

{
   graphQLErrors: GraphQLError[],
   networkError: Error,
   clientError: Error,
}

The error message should describe the error types that a particular instance of ApolloError represents. The stack trace for the instance of ApolloError might be somewhat meaningless but it will be straightforward to peek into the correct type of error (i.e. graphQLErrors, networkError or clientError) to get a stack trace that's more useful for debugging.

View layers should then pass along the instance of ApolloError if one is caught to the application code which can then deal with the error if it chooses to.

Feedback would be appreciated!

Most helpful comment

A related problem I have is that Apollo often tries to recover from errors that are unrecoverable, which causes the application to go into an infinite loop, spewing hundreds of errors on the console and consuming 100% CPU. I find that I frequently have to go into the task manager and kill the page in order to reload it, even for simple things like dumb typos in my React code, something I almost never had to do before I started using Apollo.

I wonder if apollo-client could be more selective in the kinds of exceptions it tries to catch. Or detect that an exception has been caught multiple times and just give up.

All 10 comments

I'm finding that Apollo makes debugging application errors quite difficult.

Many times errors will be silently swallowed - often I have to enable "stop on uncaught exceptions" in the Chrome debug panel order to figure out why my app is rendering a blank page.

At other times it reports the errors (I have a react ErrorDisplay component that is designed specifically to print out the stack trace and other info), but in a form that makes debugging much more cumbersome. For example, the normal stack map information supplied by webpack is not applied when printing the apollo stack traces, so all I can tell is that the error occurred somewhere in main.bundle.js, with no clue as to which source file it occurred in. I can't simply click on the link to go to the source file, which I could do if the stack trace was printed normally.

I could understand being somewhat overzealous about protecting me from errors within Apollo itself, but at least let me see the exceptions being thrown in my own code.

@viridia I agree, improving error handling is one thing I think we should focus on for the next version.

A related problem I have is that Apollo often tries to recover from errors that are unrecoverable, which causes the application to go into an infinite loop, spewing hundreds of errors on the console and consuming 100% CPU. I find that I frequently have to go into the task manager and kill the page in order to reload it, even for simple things like dumb typos in my React code, something I almost never had to do before I started using Apollo.

I wonder if apollo-client could be more selective in the kinds of exceptions it tries to catch. Or detect that an exception has been caught multiple times and just give up.

@viridia can you file an issue with a specific example for the infinite loop thing? This is the first time I hear about it.

I want to affirm @viridia s observation, apollo makes it hard to debug my app and it swallows many errors in such a way that its impossible to find the cause (except when you stop on exceptions).

store.js:13 Caught an exception! TypeError: Cannot read property 'getHostNode' of null @ store.js:13(anonymous function) @ QueryManager.js:524
store.js:14 TypeError: Cannot read property 'getHostNode' of null
聽聽聽聽at Object.getHostNode (ReactReconciler.js:64)
聽聽聽聽at ReactCompositeComponentWrapper.getHostNode (ReactCompositeComponent.js:383)
聽聽聽聽at Object.getHostNode (ReactReconciler.js:64)
聽聽聽聽at ReactCompositeComponentWrapper.getHostNode (ReactCompositeComponent.js:383)
聽聽聽聽at Object.getHostNode (ReactReconciler.js:64)
聽聽聽聽at ReactCompositeComponentWrapper.getHostNode (ReactCompositeComponent.js:383)
聽聽聽聽at Object.getHostNode (ReactReconciler.js:64)
聽聽聽聽at ReactCompositeComponentWrapper.getHostNode (ReactCompositeComponent.js:383)
聽聽聽聽at Object.getHostNode (ReactReconciler.js:64)
聽聽聽聽at ReactCompositeComponentWrapper.getHostNode (ReactCompositeComponent.js:383)(anonymous function) @ store.js:14(anonymous function) @ QueryManager.js:524

Is this something that is currently being worked on, is there any known workaround? I can't believe people would work with such a major issue going on. Don't get me wrong, apollo has made a lot of parts easier in my app, but this is a bummer.

@bkniffler we're working on error handling in general, but not this particular part just yet. I think changes will have to be made mainly in react-apollo. Maybe @jbaxleyiii or @tmeasday can take a first look?

I don't know why, but for some reason its gotten better be reinstalling my modules. Sometimes errors in my frontend will be thrown as apollo query errors (as if they happened in the backend), but at least I get stacktraces.

Any further thoughts on this? As much as Apollo has been a productivity boost for me, I'm frustrated by the amount of time I spend chasing down bugs that I ought to be able to catch in the debugger, often having to resort to 'printf'-style debugging techniques.

It would be nice if Apollo's error handler could use the source maps to unscramble the stack trace...

@viridia I think #910 will help a lot. Should be released within a day 馃檪

Closing up old issues 馃毆

Let's take this into account when designing the next API.

Was this page helpful?
0 / 5 - 0 ratings