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.