DEV Community

Cover image for Apollo Server Errors for Clients with TypeScript
Rodion Chachura
Rodion Chachura

Posted on • Originally published at

Apollo Server Errors for Clients with TypeScript

Watch on YouTube

Here I have a resolver for coupon code redemption. It should throw an error when the code doesn't exist or has a claim. Apollo server provides a few errors we can use to communicate errors to a client.

import { OperationContext } from "../../../graphql/OperationContext"
import { assertUserId } from "../../../auth/assertUserId"
import * as appSumoCodesDb from "../db"
import { UserInputError } from "apollo-server-lambda"

interface Input {
  code: string

export const redeemAppSumoCode = async (
  _: any,
  { input: { code } }: { input: Input },
  context: OperationContext
) => {
  const userId = assertUserId(context)

  const appSumoCode = await appSumoCodesDb.getAppSumoCodeById(code)
  if (!appSumoCode || appSumoCode.userId !== userId) {
    throw new UserInputError("Invalid code")

  // ...
Enter fullscreen mode Exit fullscreen mode

We can go to the source code and see that they all extend ApolloErro. So if we need a custom error, we can copy one of the classes from here and change the name with a code.

export class UserInputError extends ApolloError {
  constructor(message: string, extensions?: Record<string, any>) {
    super(message, "BAD_USER_INPUT", extensions)

    Object.defineProperty(this, "name", { value: "UserInputError" })
Enter fullscreen mode Exit fullscreen mode

Apollo Server always responds with 200, but if API threw an error, we'll receive errors with a response. I formatted the error to include only the message and extensions. If we want to provide extra information, we can add an object as a second parameter to ApolloError, and it will appear in the extensions object. To omit stack trace from extension, set NODE_ENV to production.

const server = new ApolloServer({
  // ...
  formatError: ({ message, extensions }) => {
    return {
Enter fullscreen mode Exit fullscreen mode

I run Apollo Server on AWS Lambda and use Sentry for error monitoring. Don't forget to pass ignoreSentryErrors, otherwise, your lambda will crash if you reach Sentry's quote.

exports.handler = Sentry.AWSLambda.wrapHandler(server.createHandler(), {
  ignoreSentryErrors: true,
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

11 Tips That Make You a Better Typescript Programmer


1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields


Read the whole post now!