UNPKG

4.25 kBMarkdownView Raw
1---
2title: apollo-link-error
3description: Handle and inspect errors in your GraphQL network stack.
4---
5
6Use this link to do some custom logic when a GraphQL or network error happens:
7
8```js
9import { onError } from "apollo-link-error";
10
11const link = onError(({ graphQLErrors, networkError }) => {
12 if (graphQLErrors)
13 graphQLErrors.forEach(({ message, locations, path }) =>
14 console.log(
15 `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
16 )
17 );
18 if (networkError) console.log(`[Network error]: ${networkError}`);
19});
20```
21
22Apollo Link is a system of modular components for GraphQL networking. [Read the docs](https://www.apollographql.com/docs/link/#usage) to learn how to use this link with libraries like Apollo Client and graphql-tools, or as a standalone client.
23
24## Callback
25
26Error Link takes a function that is called in the event of an error. This function is called with an object containing the following keys:
27
28* `operation`: The Operation that errored
29* `response`: The result returned from lower down in the link chain
30* `graphQLErrors`: An array of errors from the GraphQL endpoint
31* `networkError`: Any error during the link execution or server response, that wasn't delivered as part of the `errors` field in the GraphQL result
32* `forward`: A reference to the next link in the chain. Calling `return forward(operation)` in the callback will retry the request, returning a new observable for the upstream link to subscribe to.
33
34Returns: `Observable<FetchResult> | void` The error callback can optionally return an observable from calling `forward(operation)` if it wants to retry the request. It should not return anything else.
35
36## Error categorization
37
38An error is passed as a `networkError` if a link further down the chain called the `error` callback on the observable. In most cases, `graphQLErrors` is the `errors` field of the result from the last `next` call.
39
40A `networkError` can contain additional fields, such as a GraphQL object in the case of a [failing HTTP status code](http#errors) from [`apollo-link-http`](http). In this situation, `graphQLErrors` is an alias for `networkError.result.errors` if the property exists.
41
42## Retrying failed requests
43
44An error handler might want to do more than just logging errors. You can check for a certain failure condition or error code, and retry the request if rectifying the error is possible. For example, when using some form of token based authentication, there is a need to handle re-authentication when the token expires. Here is an example of how to do this using `forward()`.
45```js
46onError(({ graphQLErrors, networkError, operation, forward }) => {
47 if (graphQLErrors) {
48 for (let err of graphQLErrors) {
49 switch (err.extensions.code) {
50 case 'UNAUTHENTICATED':
51 // error code is set to UNAUTHENTICATED
52 // when AuthenticationError thrown in resolver
53
54 // modify the operation context with a new token
55 const oldHeaders = operation.getContext().headers;
56 operation.setContext({
57 headers: {
58 ...oldHeaders,
59 authorization: getNewToken(),
60 },
61 });
62 // retry the request, returning the new observable
63 return forward(operation);
64 }
65 }
66 }
67 if (networkError) {
68 console.log(`[Network error]: ${networkError}`);
69 // if you would also like to retry automatically on
70 // network errors, we recommend that you use
71 // apollo-link-retry
72 }
73 }
74);
75```
76
77Here is a diagram of how the request flow looks like now:
78![Diagram of request flow after retrying in error links](https://i.imgur.com/ncVAdz4.png)
79
80One caveat is that the errors from the new response from retrying the request does not get passed into the error handler again. This helps to avoid being trapped in an endless request loop when you call forward() in your error handler.
81
82## Ignoring errors
83
84If you want to conditionally ignore errors, you can set `response.errors = undefined;` within the error handler:
85
86```js
87onError(({ response, operation }) => {
88 if (operation.operationName === "IgnoreErrorsQuery") {
89 response.errors = undefined;
90 }
91});
92```