Search code examples
graphqlapollostackapollo-server

How can I signal an error in a graphql apollo-server mutation resolver?


The documentation tells us that a resolver has this form:

fieldName: (obj, args, context, info) => result

And that result is null or undefined if "the object could not be found".

What about other errors - for example, if the access is not authorised?

It appears that you can't directly "return" an error, because the result has to match the schema.

I've tried throwing an exception in the resolver, and this almost does the right thing: the client gets an ApolloError with the exception message in it: that's great. BUT the apollo-server issues a stack trace, as if the exception wasn't handled. That doesn't seem right.

Hence the question: how should this be done?


The apollo-server stack trace, in case it helps:

Error: test exception message
at /Users/mgregory/NRN/src/agreeonit/apollo_server/resolvers/mutationResolvers.js:29:17
at tryCatcher (/Users/mgregory/NRN/src/agreeonit/apollo_server/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/Users/mgregory/NRN/src/agreeonit/apollo_server/node_modules/bluebird/js/release/promise.js:510:31)
at Promise._settlePromise (/Users/mgregory/NRN/src/agreeonit/apollo_server/node_modules/bluebird/js/release/promise.js:567:18)
at Promise._settlePromise0 (/Users/mgregory/NRN/src/agreeonit/apollo_server/node_modules/bluebird/js/release/promise.js:612:10)
at Promise._settlePromises (/Users/mgregory/NRN/src/agreeonit/apollo_server/node_modules/bluebird/js/release/promise.js:691:18)
at Async._drainQueue (/Users/mgregory/NRN/src/agreeonit/apollo_server/node_modules/bluebird/js/release/async.js:138:16)
at Async._drainQueues (/Users/mgregory/NRN/src/agreeonit/apollo_server/node_modules/bluebird/js/release/async.js:148:10)
at Immediate.Async.drainQueues (/Users/mgregory/NRN/src/agreeonit/apollo_server/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:574:20)
at tryOnImmediate (timers.js:554:5)
at processImmediate [as _immediateCallback] (timers.js:533:5)

Solution

  • I discovered that the stack trace is being issued because the default setting of GraphQLOptions.debug is true.

    Setting that to false in the initialisation of the server cleans everything up.

    Conclusion: throwing an exception is the right way to do it.