apollographql / apollographql/apollo-server
Allow plugins to throw meaningful GraphQL errors
- Dominant language
- TypeScript
- Stars
- 14k
- Forks
- 2k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 2
Description
For most plugin hooks, an error thrown from the hook results in an "Internal Server Error" response to the client. I'd like to propose that if a plugin throws a `GraphQLError` instance, Apollo Server should consider that to mean "the plugin's author _intended_ for the client to get this error as a response to their query", and handle it similarly to how such an error would be handled if it came from a resolver - namely, to be processed by the [`sendErrorResponse()`][1] function and not masked by an internal server error.
I understand the discussions in #7278 and #7375 and my specific use-case cannot be solved from within the context factory function. The hook I need to use is `responseForOperation`; while that does allow me to return a response directly, going that route when I need to respond with an error means that I lose the existing logic for error handling which Apollo already implements (call `didEncounterErrors` hooks, properly format errors in the response, including - or not including, as per server configuration - the stack trace etc). And more importantly, my specific use-case isn't even all that relevant - I believe that there may be use cases for _most_ request lifecycle hooks where a plugin might want to terminate the execution of a particular request and return a meaningful error message to the user, and there is currently no sane way to do that. Allowing errors which are instances of (a descendant of) `GraphQLError` to pass through to the client seems like a decent tradeoff between security against unexpected errors and flexibility for plugin authors.
[1]: https://github.com/apollographql/apollo-server/blob/main/packages/server/src/requestPipeline.ts#L660
Contributor guide
Research direction
Start in packages/server/src/requestPipeline.ts around sendErrorResponse(), then trace how errors thrown by the responseForOperation hook are currently handled. Compare this with resolver GraphQLError handling and the existing didEncounterErrors and error-formatting flow. Done means an intentionally thrown GraphQLError reaches the normal client error response path without changing the treatment of unexpected errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- graphql, typescript
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100