question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to correctly propagate errors from plugins?

See original GitHub issue

I’m writing an Apollo Server plugin that validates a presence of a certain HTTP header. It looks like this:

import { ApolloServerPlugin } from 'apollo-server-plugin-base';
import { OperationDefinitionNode } from 'graphql';

export const myPlugin: ApolloServerPlugin = {
  requestDidStart() {
    return {
      didResolveOperation(context) {
        if (!headerIsValid(context.request.http!.headers.get('x-special-header'))) {
          throw new Error('header not valid');
        }
      },
    };
  },
};

I’m doing that in a plugin because I need access to a parsed query so that I can distinguish introspection queries and normal queries, and I didn’t find a better place to do it, see here.

Previously, I had this logic in the context: () => {...} function inside new ApolloServer constructor and when I threw the error there, it was returned to the client and not logged to console.

When I throw an error in a plugin, it is sent to the client but also logged to a console, as if it was an uncaught error.

Am I doing it correctly? Is there a way to avoid having a full stack trace in the server console / logs? My code does not have any error, I just want to indicate a problematic query to the user.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:12 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
aaronleesmithcommented, Jun 12, 2020

To give a concrete followup to anyone stumbling on this issue, here’s what I’ve learned.

Throwing an error from inside the plugin methods will cause didEncounterErrors to fire. The only plugin method which lets you actually send a response is responseForOperation. There are two ways, therefore, to modify the response:

  1. in responseForOperation
  2. By modifying context.response.

If you follow the code, you’ll find that before issuing the HTTP response, the Apollo code checks to see if erorrs.length is non-zero and that data is null. If this is the case, it responds with a 400 status code and an object called “error” which contains the errors. Essentially, it doesn’t know what to do with it at that point.

In fact, returning from responseForOperation with errors, but no data object, will cause the above to happen as well.

To address my problem, I am returning the a properly spec’d GQl response, including errors and data with null values for each of context.operation.selectionSet.selections. This makes the response mimic what would be expected when throwing any error inside of resolvers. This special case exists because we want to stop execution from inside of a plugin.

1reaction
aaronleesmithcommented, Jun 11, 2020

@borekb I am struggling with a similar problem. In my case, when I throw an error from a plugin lifecycle method, the value returned to the client is

{
  "error": {
    "errors": [...]
  }
}

Which is not up to spec AFAIK and should instead be

{
  "errors": [...],
  "data": {... null}
}

Have you seen this behavior too as it pertains to error handling in plugins?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Developers - How to correctly propagate errors from plugins? -
I'm writing an Apollo Server plugin that validates a presence of a certain HTTP header. It looks like this: import { ApolloServerPlugin }...
Read more >
Web server plugin propagation fails during installation of ... - IBM
2. In the WebSphere Administrative console click Servers->Server Types->Web servers. 3. Locate and open the web server definition for your web ...
Read more >
50 Most Common WordPress Errors and How to Fix Them
Learn how to fix some of the most most common WordPress errors (Step ... of this error is a plugin or theme failing...
Read more >
React Error Handling and Logging Best Practices
Proper error handling is critical for applications to function normally. ... react-error-boundary will propagate that to the nearest error ...
Read more >
Improving TypeScript error handling with exhaustive type ...
Failing to deal with these errors correctly creates programmer ... and the error propagated up, disrupting the regular flow of the code.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found