express-graphql icon indicating copy to clipboard operation
express-graphql copied to clipboard

Swallow GraphQL errors by Express

Open Yoann-Abbes opened this issue 3 years ago • 6 comments

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)

Yoann-Abbes avatar Apr 28 '22 14:04 Yoann-Abbes

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.

divmgl avatar Nov 28 '22 04:11 divmgl

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

saihaj avatar Nov 28 '22 18:11 saihaj

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

Yoann-Abbes avatar Nov 30 '22 17:11 Yoann-Abbes

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

mxmaxime avatar Dec 16 '22 13:12 mxmaxime

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

stevenkissack avatar Dec 26 '22 11:12 stevenkissack

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!

enisdenjo avatar Mar 20 '23 12:03 enisdenjo