React-apollo: How to catch server or network errors from react-apollo Query?

Created on 29 Nov 2016  路  16Comments  路  Source: apollographql/react-apollo

So after reading docs, issues and Stackoverflow I am still at loss how to handle this, thus I post this issue.

How do I catch the error when I have network problems during a Query, or when my server reports an error during a Query? Currently I am getting Uncaught (in Promise) ApolloError, but I can't figure where I should add code to catch this.

(I've got it done for mutations, because there I get a callback which returns a Promise that I can .catch(), but queries don't have that...)

I have tried adding an Afterware to the networkInterface, but the client crashes before it is reached.

This is an example error (when the server is unhappy because my authentication token has expired):

Uncaught (in promise) ApolloError
    extraInfo: undefined
    graphQLErrors: Array[1]
    0: Objectmessage: "jwt expired"
    __proto__: Object
    length: 1
    __proto__: Array[0]
    message: "GraphQL error: jwt expired"
    networkError: undefined
    stack: "Error
        at new ApolloError (webpack:///./~/apollo-client/errors/ApolloError.js?:14:22)
        at eval (webpack:///./~/apollo-client/core/QueryManager.js?:545:27)"
    __proto__: Error(anonymous function) @ QueryManager.js:566

The request is generated from a Component with the react-apollo code:

const accountQuery = gql`
query ($accountId: Int!) {accountById(id:$accountId) {
  firstName,
  lastName,
  fullName
}}`;

export default graphql( accountQuery, {
    options: ( { accountId } ) => ({ variables: { accountId: accountId || 0 } }),
} )( AccountService );

Relevant package versions:

"apollo-client": "^0.5.6",
"graphql-tag": "^0.1.17",
"react-apollo": "^0.6.0",

So my question is: Where do I add an error handler???

Most helpful comment

Seems like everything is ok )
Instead of using console.log(error) need to use console.log(error.graphQLErrors). We see error message instead of object because toString method calls.

All 16 comments

Update: I have now also tried to use the withApollo HOC which gives me a Promise returned from this.props.client.query(), but even if I .catch() this Promise I cannot catch the GraphQL errors, and my client still crashes :-(

So... maybe I should file this with Apollo Client instead?

I suppose so. Can you trace the error back to the line in AC where it is coming from?

The line numbers are in the TB log that I posted above, aren't they ?
apollo-client/core/QueryManager.js?:545:27

So apparently this was an Apollo Client bug (https://github.com/apollostack/apollo-client/issues/891) which was fixed in AC 0.5.8 two days ago, and all is now fine :-)

I still see this error message:

ApolloError.js:32 Uncaught (in promise) Error: Network error: Failed to fetch
    at new ApolloError (ApolloError.js:32)
    at QueryManager.js:248
    at <anonymous>

I use apollo-react 1.4.3 and apollo-client 1.9.0

Same here. Even if I access this.props.data.error in my Container component, which some of other posts suggested would fix the error.

@HriBB, @psamim, guys, have you found the solution?

I also have such error in catch handler of my mutation

ERROR Error: GraphQL error: validation
    at new ApolloError (bundle.js?e00e5e47c4852bcd0c59:21132)
    at bundle.js?e00e5e47c4852bcd0c59:73317
    at <anonymous>

Seems like everything is ok )
Instead of using console.log(error) need to use console.log(error.graphQLErrors). We see error message instead of object because toString method calls.

I'm seeing this as well 鈥撀爄n our case are using compose, graphql and returning props and the component handles the error prop:

class MyComponent extends React.Component {
  render () {
    if (this.props.error) {
        return <ErrorState />
    }
    // ... other stuff
  }
}

compose(
  graphql(query, {
    props ({ data, ownProps }) {
      return { ...ownProps, error: data.error, /* other props */ }
    }
  })
)(MyComponent)

According to the docs, this seems like it should work. Is this an expectation that the exact shape of the apollo data be preserved when passed to the component for handling via props (e.g. props.data.error)?

{
  "dependencies": {
    "apollo-client": "^1.9.1",
    "graphql": "^0.10.5",
    "react-apollo": "^1.4.14",
    "...other deps": ""
  }
}

Same here.

There are two different types of errors (Unhandled and Uncaught):

  1. react-apollo.browser.umd.js:566 Unhandled (in react-apollo) Error: GraphQL error:
  2. ApolloError.js:36 Uncaught (in promise) Error: GraphQL error:

I'm able to handle the first one (Unhandled Error) by accessing the props.data.error attribute:

props: ({data: {loading, me, error}}) => {
  if (error) {
    ...
  }
}

But it seems not possible to handle or to get rid of the second one (Uncaught Error).

Am I missing something here?

@axax what you're missing is network interface afterware: http://dev.apollodata.com/core/network.html#networkInterfaceAfterware

networkInterface.useAfter([{
  applyAfterware({ response }, next) {
    if (response.status === 502) {
      // Bad gateway, let's not forward this to the client and avoid some potential crashed
      store.dispatch({ error: ' Some error' };
      return;
    }
    next();
  }
}]);
const client = new ApolloClient({
  networkInterface,
});

The error in props.data.error is a GraphQL error. As far as I know these can only be sent over 200 (success) responses from the server. So any kind of 404, 498, 502, etc will have to be caught in the afterware.

To be honest this is kind of annoying and i wish this would cascade down into the graphql container. I have a crash in my app due to random 502s that end up returning viewer: null and resetting cached data that I depend on to exist.

Catching this error in the above way doesn't work very well because in some instances the error is context-specific. For example, if I push to a detail screen (React Native) and i use query splitting to fetch the extra data and that returns a 502, the cached summary data could potentially be wiped out by that error and cause crashes since I assume summary.value to exist.

In order to gracefully catch this error I should navigate the user back to the previous screen and not forward the response from the afterware. However, in the afterware context it's unaware of navigation context - in some cases I might not want to make a user go back.

An idea that I might try implement is to actually mutate the response.status into a 200 within the afterware in order to handle the error within the container. I'll report back with how this goes.

How'd it go?

react-apollo > > error-handling

And with Apollo 1?

I was recently trying to do this with Apollo 1 and ended up using a nice little HOC and Apollo Link State solution.

Was this page helpful?
0 / 5 - 0 ratings