6. Resolving a mutation with errors
2m

🚨 Handling the error case

As we saw in the REST API, it's possible to get a 404 Not Found response when trying to update a track that doesn't exist. Let's look at how to return the appropriate fields when that happens.

Let's open up the resolvers.js file again in the server/src folder.

We've got our successful response for our incrementTrackViews mutation ready. To handle the situation where the TrackAPI call throws an error, let's wrap this section in a try block.

When the error is thrown, we'll make sure to catch it by adding a catch, which takes the error as a parameter.

incrementTrackViews: async (_, {id}, {dataSources}) => {
try {
const track = await dataSources.trackAPI.incrementTrackViews(id);
return {
code: 200,
success: true,
message: `Successfully incremented number of views for track ${id}`,
track
};
} catch (err) {
return {
// we'll return a new object here
};
}
},

Then, we return an object with the same properties as the object in the success case, but with different values.

We could set the code to be 404, but we can also be more dynamic and use the values that Apollo Server and the RESTDataSource class provide. When an error occurs, Apollo Server attaches an extensions field to that error that contains relevant error details.

In this case, as our TrackAPI extends RESTDataSource, this extensions object will be enriched with a response property, which provides some additional information about the HTTP response itself. We can return the status property, which refers to the HTTP status code. Perfect to use here!

code: err.extensions.response.status,

Next, we can set our success property to false.

success: false,

For the message property, we can craft a custom one, but let's use another value from the same extensions.response object. That's the extensions.response.body property. It makes this value more dynamic, since it might return other types of errors in the future.

message: err.extensions.response.body,

Finally, we'll add a track property and set it to null, because the object was not successfully modified.

Which of the following statements are true about the error.extensions fields returned by the server?

The incrementTrackViews resolver should now look like this, with the error handling added in:

incrementTrackViews: async (_, {id}, {dataSources}) => {
try {
const track = await dataSources.trackAPI.incrementTrackViews(id);
return {
code: 200,
success: true,
message: `Successfully incremented number of views for track ${id}`,
track
};
} catch (err) {
return {
code: err.extensions.response.status,
success: false,
message: err.extensions.response.body,
track: null
};
}
},

The resolver handles both a successful response and possible errors. Which of these are true about the return objects for those two cases?

Code Challenge!

We start with the same assignSpaceship Mutation resolver example as in the previous code challenge. This time, we assume the dataSources.spaceAPI.assignSpaceshipToMission() call will return an error. Modify the following piece of code to properly handle the error returned by the API and return a properly formatted object that conforms to the schema definition of the AssignSpaceshipResponse type. Remember to use a try/catch block and to return dynamic error data when possible.

Awesome, this mutation is ready to go and ready to be tested in the Apollo Studio Explorer! Let's get to it.

Previous
Next