graphql / express-graphql

Create a GraphQL HTTP server with Express.
MIT License
6.34k stars 538 forks source link

Swallow GraphQL errors by Express #803

Open Yoann-Abbes opened 2 years ago

Yoann-Abbes commented 2 years ago

Hi

I'm having issues using a simple express error handler middleware to swallow errors thrown in GraphQL resolvers

For example, I would have:

GQLside

function gqlQuery {
    if (!something) {
      throw new Error('Some Error');
    }

Express side

app.use(
      '/graphql',
     {
      schema,
      context,
      graphiql: true,
      customFormatErrorFn: (error: any) => {
        const errParams = {
          message: error.message,
          locations: error.locations,
          stack: error.stack,
        };
        return errParams;
      },
);

app.use((err, req, res, next) => {
      logger.info('Express middleware error handler')
      res.sendStatus(200)
      next();
    });

What I need, is when inside the resolver I throw the Some Error, Express swallows it inside it's middleware. It does not work

The only way I managed to do it, is by throwing inside the customFormatErrorFn function:

customFormatErrorFn: (error: any) => {
        const errParams = {
          message: error.message,
          locations: error.locations,
          stack: error.stack,
        };
        if (error.originalError.message.startsWith('Some Error')) {
          throw error;
        }

If I do that, the Express middleware is being called.

But GraphQL returns a bad formatted response

{
  "message": "Unexpected token O in JSON at position 0",
  "stack": "SyntaxError: Unexpected token O in JSON at position 0"
}

I don't understand how I can simply manage GraphQL errors through Express. I'm certainly doing something wrong

My final goal is to catch those errors before they are sent to the client (to chose if I log them for example)

divmgl commented 1 year ago

So this issue was opened in April. Did you find a solution to this? I'm running into this right now and it's looking pretty dire.

saihaj commented 1 year ago

@divmgl this project is deprecated. Checkout https://github.com/graphql/express-graphql/pull/817

Yoann-Abbes commented 1 year ago

@divmgl No sorry, I let i go If you find a solution I would be interested too

mxmaxime commented 1 year ago

Hi, Exact same situation here. I was digging but I think I'll migrate my code to remove this dependency :/

stevenkissack commented 1 year ago

Trying my best to understand the exact scenario you are trying to solve & I know this library is deprecated but I run it in production with graphql-shield and battled with error handling myself so much that I patched it for our use case. Some possibly helpful tips although untested:

Instead of filtering based on the message, use a custom error with an errorType like so:

import { CustomError } from 'ts-custom-error'

export class ApiError extends CustomError {
  public errorType: string
  public constructor(
    public code: string,
    message: string,
    public originalError?: Error,
  ) {
    super(message)
    this.errorType = 'ApiError'
  }
}

function someResolver() {
  throw new ApiError('oh_no', 'Oh No!', optionalOriginalErrorHere)
}

This will come through to your customFormatErrorFn, and you can then handle it based on the type. The next part is returning a valid GraphQL response. Look at the function graphqlMiddleware inside the the library index.ts and you will see how they construct it:

result = { data: undefined, errors: error.graphqlErrors }

I personally have a lot more custom logic painfully wired in to the library, but if you're stuck using this library, maybe it will help you find the right answer for you

enisdenjo commented 1 year ago

This library has been deprecated and this repo will be archived soon. It has been superseded by graphql-http.

Furthermore, if you seek a fully-featured, well-maintained and performant server - I heavily recommend GraphQL Yoga!