Alexandra Lim | Front End DeveloperSkip to content
Alexandra Lim

GraphQL error policies in Apollo Client

GraphQL, Apollo GraphQL, Apollo Client3 min read

Recently at work, my tech lead and I ran into a very interesting edge case involving data returned from a GraphQL query. In the query response, we saw that partial data was being returned along with an error, but our app's middleware was intercepting the error message and redirecting us to a 404 page instead. Why was the error message taking priority and why were we not shown the partial data even if it was available? I was only missing one field, and the rest of the data could be displayed.

Let's recreate the query response for this post. Imagine we are querying data for a cat adoption site with the help of Apollo Client, and the response looked like this:

  data: {
    name: "Sherlock",
    age: 6,
    breed: "Domestic shorthair",
    color: "Brown tabby",
    sex: "male",
    likes: null,
  errors: [{ message: "Failed to get likes." }],

Instead of the likes field being populated with an array like ["belly rubs", "treats"], it returns null with an error message accompanying the response. In our case at work, the error was related to user permissions, but the reason behind the error is not important here.

The type of error we've received is considered a resolver error. A resolver error is defined as "an error occurred while attempting to populate a query field". If a resolver error occurs, partial data can still be returned. Great! If that's the case, where's our data though?

It turns out that by default, Apollo Client ignores the partial data and doesn't cache it. It populates the error.graphQLErrors array of your useQuery call instead. This is also known as setting the errorPolicy to none.

In Apollo, there are three error policies that can be set: none, ignore, and all. The following table describes the three error policies, and are copied directly from the Apollo docs:

noneIf the response includes GraphQL errors, they are returned on error.graphQLErrors and the response data is set to undefined even if the server returns data in its response. This means network errors and GraphQL errors result in a similar response shape. This is the default error policy.
ignoregraphQLErrors are ignored (error.graphQLErrors is not populated), and any returned data is cached and rendered as if no errors occurred.
allBoth data and error.graphQLErrors are populated, enabling you to render both partial results and error information.

In my case, I want to set the error policy to ignore. I don't care about the error message, I just want to display any partial data returned in the response. By setting it to ignore, Apollo pretends an error hasn't occurred, and the partial data is cached and rendered as normal.

To do so, I pass in an object with the errorPolicy value set to ignore as an argument into my useQuery hook:

const { loading, data } = useCatInfoQuery(CAT_INFO_QUERY, { errorPolicy: "ignore" });

If I want to access both the partial data and error, I'd set the error policy to all. I would also destructure error from the useQuery hook to access error.graphQLErrors:

const { loading, data, error } = useCatInfoQuery(CAT_INFO_QUERY, { errorPolicy: "all" });

console.log(error.graphQLErrors);  // logs an array of error messages

And that's it! With ignore or all, if any resolver error occurs, the rest of my data from the useCatInfoQuery will still render in my component, provided that I've added the right conditional logic to show the data.

If you have any questions or notice an error in this post, drop me a line at [email protected].