DEV Community

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

Posted on • Originally published at radzion.com

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({
  typeDefs,
  resolvers,
  // ...
  formatError: ({ message, extensions }) => {
    return {
      message,
      extensions,
    }
  },
})
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

Postgres on Neon - Get the Free Plan

No credit card required. The database you love, on a serverless platform designed to help you build faster.

Get Postgres on Neon

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up