11

I'm trying to use a custom error with apollo-server and it seems that my custom error has a property (code) that isn't available from within formatError.

import ExtendableError from 'es6-error'

export default class MyError extends ExtendableError {
  constructor(args) {
    let code = Object.keys(args)[0]
    let message = Object.values(args)[0]
    super(message)
    this.code = code
  }
}

I have a simple error handler works something like this:

let INVALIDREQUEST = 'invalid request'
let e = new MyError({INVALIDREQUEST})
console.log(e.code) // => "INVALIDREQUEST"

I'm having trouble because when I log error.code from within formatError it's not available.

formatError: function (error) {
  console.log(error.code) // => undefined
  return error
}

How can I propagate custom properties (like code) of error from within formatError?

ThomasReggi
  • 55,053
  • 85
  • 237
  • 424

3 Answers3

14

Because Apollo Server uses GraphQL.js, we can find the solution by digging deep there: https://github.com/graphql/graphql-js/blob/44f315d1ff72ab32b794937fd11a7f8e792fd873/src/error/GraphQLError.js#L66-L69

Essentially, the GraphQL.js reference implementation catches any errors in your resolvers, and delivers them to the formatError function, but it wraps them in a special GraphQL-specific error object, with properties like path, positions, and source.

You can find the original error you threw from the resolver on the originalError field of the error object in formatError, like so:

formatError: function (error) {
  console.log(error.originalError.code)
  return error
}
stubailo
  • 6,077
  • 1
  • 26
  • 32
  • 1
    why node log is different from graphiql? in graphiql i can see the states when i add in formaterror: error.state = error.originalError; but in node console i see just: GraphQLError ( .. at locatedError ..) path, positions, and source. can I see in the console on node, my state property? – stackdave Sep 18 '17 at 00:43
5

With Apollo, you can easily multiplex the errors array in the graphql response for both graphql errors AND custom errors that are machine readable using this package:

https://github.com/thebigredgeek/apollo-errors

Andrew Rhyne
  • 5,060
  • 4
  • 28
  • 41
1

Usually it's enough. You can define error code (2 parameter), error message and any custom object in extensions (3 parameter)

     throw new ApolloError('User already exist',
                           'DUPLICATE',
                           { 'session': session })
Aksenov Vladimir
  • 677
  • 1
  • 6
  • 16
  • Throwing ANY `ApolloeError` or a subclass thereof will always strip the message and insert `Unexpected error value: { extensions: { code: }}` instead of _actually just passing up the error or presenting the error as thrown._ The message is *always* omitted, which defeats the whole process of using ApolloError type if `formatError` always destroys what you actually want to throw. – Benjamin R Jun 22 '21 at 12:22