How to Handle Errors in GraphQL

Error handling in GraphQL is an essential aspect of building robust APIs. Unlike traditional REST APIs, where HTTP status codes are used to indicate errors, GraphQL uses a unified response format that includes errors in the response body. This allows clients to receive detailed information about what went wrong while still getting partial data when possible.

1. GraphQL Error Structure

When an error occurs in a GraphQL operation, the response will include an errors field in addition to the data field. The errors field is an array of error objects, each containing information about the error.

Sample Error Response


{
"data": {
"user": null
},
"errors": [
{
"message": "User not found",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"user"
]
}
]
}

2. Throwing Errors in Resolvers

In GraphQL resolvers, you can throw errors to indicate that something went wrong. You can use standard JavaScript Error objects or create custom error classes to provide more context.

Example of Throwing Errors


const resolvers = {
Query: {
user: (parent, { id }) => {
const user = users.find(u => u.id === id);
if (!user) {
throw new Error("User not found");
}
return user;
},
},
};

3. Custom Error Classes

For better error handling, you can create custom error classes that extend the base Error class. This allows you to include additional properties, such as error codes or status.

Example of a Custom Error Class


class UserNotFoundError extends Error {
constructor(message) {
super(message);
this.name = "User NotFoundError";
}
}

const resolvers = {
Query: {
user: (parent, { id }) => {
const user = users.find(u => u.id === id);
if (!user) {
throw new UserNotFoundError("User not found");
}
return user;
},
},
};

4. Error Handling Middleware

You can also implement error handling middleware in your GraphQL server to catch and process errors globally. This is useful for logging errors or transforming them before sending the response.

Example of Error Handling Middleware


const { ApolloServer } = require('apollo-server');

const server = new ApolloServer({
typeDefs,
resolvers,
formatError: (err) => {
// Log the error
console.error(err);
// Return a custom error message
return new Error("Internal server error");
},
});

5. Client-Side Error Handling

On the client side, you can handle errors by checking the errors field in the response. This allows you to provide feedback to users or take appropriate actions based on the error type.

Example of Client-Side Error Handling


fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: '{ user(id: "1") { name } }',
}),
})
.then(response => response.json())
.then(data => {
if (data.errors) {
console.error("GraphQL Errors:", data.errors);
// Handle errors accordingly
} else {
console.log("User data:", data.data.user);
}
});

Conclusion

Handling errors in GraphQL requires a different approach compared to traditional REST APIs. By throwing errors in resolvers, using custom error classes, implementing error handling middleware, and managing errors on the client side, you can create a robust error handling strategy for your GraphQL API. This ensures that clients receive meaningful feedback and can respond appropriately to issues that arise during data fetching.