DEV Community

Chris Held
Chris Held

Posted on

Custom Error classes with Apollo Server

Recently, I was tasked with upgrading an older version of apollo-server-express with the newer @apollo/server package. apollo-server-express is approaching end of life this year and we wanted to take advantage of all of the new features apollo had introduced in the last two years. While there were several differences involved in the upgrade, one particular change caught our attention—the removal of support for custom error classes that we had used extensively used in our application. The challenge we faced was to find a solution that allowed us to seamlessly transition to the new version without disrupting our existing users.

In the previous version, we handled unauthorized access much like the following code snippet:

if (!hasAccess) {
    // Removed!
    throw new ForbiddenError("You don't have access");
}
Enter fullscreen mode Exit fullscreen mode

The recommendation from the apollo upgrade docs was to replace these instances with GraphQLError, like so:

if (!hasAccess) {
    throw new GraphQLError("You don't have access", extensions: { code: 'FORBIDDEN' });
}
Enter fullscreen mode Exit fullscreen mode

While this technically resolved our problem, it felt cumbersome to add the extensions property to all our old errors. However, we found a simple and elegant solution inspired by Apollo's previous approach: extending GraphQLError to create our own custom errors.

To accomplish this, we defined our custom error classes as follows:

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

export class ForbiddenError extends GraphQLError {
  constructor(message: string) {
    super(message, {
      extensions: {
        code: 'FORBIDDEN',
        http: {
          status: 403,
        },
      },
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Creating our own custom errors allows us to encapsulate setting and sending extensions in one place, which ensures we’re consistent with how we’re responding to these errors. As an added bonus it gave us an opportunity to send down a 401 or 403 status code when throwing the appropriate error, which had been requested by a few of our clients.

This turned what could have been a lot of work into a really straightforward upgrade path. By simply updating the imports, we were able to resolve the majority of our issues while maintaining the same functionality. This meant that consumers of our API wouldn't need to make any changes to adapt to our system, ensuring a smooth transition.

Top comments (1)

Collapse
 
jelugbadebo profile image
jelugbadebo

Hi Chris,

Came across your post. I tried this (and many other configurations), and can't seem to override the default 200 or 500 status code response from GraphQL in Apollo Explorer when testing my resolvers.

I'm trying to override the default status codes (200 or 500) GraphQL responds with as laid out here: apollographql.com/docs/apollo-serv...

Any idea on how to override these status codes?

Thanks,
Johnson