Best Practices for Error Handling in GraphQL with Apollo Server 4

Introduction

Welcome to the lesson on Best Practices for Error Handling in GraphQL. In this lesson, we will explore how to handle errors effectively in your GraphQL API using Apollo Server 4 and TypeScript. Proper error handling is crucial for building reliable and user-friendly applications.

How GraphQL Handles Errors and Common Error Types

In REST API, a single error usually results in the entire request failing with an HTTP error status. However, In GraphQL, partial success is possible because errors are isolated to specific fields.

GraphQL treats errors as part of the response format. If any field in a query fails, it includes an errors array in the response. Common error types include:

  • User Input Errors
  • Authentication Errors
  • Validation Errors
  • System Errors

Creating Custom Error Classes

Since Apollo Server 4 removed built-in error classes, we'll create our own error handling system:

import { GraphQLError } from 'graphql';

export class ValidationError extends GraphQLError {
  constructor(message: string) {
    super(message, {
      extensions: {
        code: 'BAD_USER_INPUT',
        http: { status: 400 }
      }
    });
  }
}

export class NotFoundError extends GraphQLError {
  constructor(message: string) {
    super(message, {
      extensions: {
        code: 'NOT_FOUND',
        http: { status: 404 }
      }
    });
  }
}

export class AuthenticationError extends GraphQLError {
  constructor(message: string) {
    super(message, {
      extensions: {
        code: 'UNAUTHENTICATED',
        http: { status: 401 }
      }
    });
  }
}

Implementing Basic Error Handling in Resolvers

Let's implement error handling using our custom error classes:

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';

interface Book {
  id: string;
  title: string;
  author: string;
}

const books: Book[] = [
  { id: '1', title: 'The Hobbit', author: 'J.R.R. Tolkien' },
  { id: '2', title: 'Harry Potter', author: 'J.K. Rowling' }
];

const resolvers = {
  Query: {
    book: (_: unknown, { id }: { id: string }) => {
      const book = books.find(book => book.id === id);
      if (!book) {
        throw new NotFoundError(`Book with ID ${id} not found`);
      }
      return book;
    },
  }
};
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal