What's the best way to send custom HTTP status codes for GraphQL errors in an Express app?

I’m working on a React and Express app with GraphQL. I’m having trouble getting the right HTTP status codes to show up on the frontend when there’s an error in the backend.

Here’s what’s happening:

  • My backend uses graphql-http and Express
  • I’ve set up error handling in the backend
  • The frontend gets error messages, but always sees a 200 OK status
  • I want to send specific codes like 409 for conflicts or 422 for bad data

I’ve tried:

  1. Adding statusCode to error extensions
  2. Checking res.ok on the frontend
  3. Using error middleware in Express

But nothing seems to work. The frontend always gets a 200 OK, even when there’s an error.

How can I fix this? Is there a trick to sending the right status codes with GraphQL errors in Express? Any ideas would be super helpful!

hey i’ve delt with this before. try using apollo server instead of graphql-http. it has built-in support for custom status codes. you can set httpStatusCode in your errors like this:

throw new ApolloError(‘Error message’, ‘ERROR_CODE’, { httpStatusCode: 409 });

this should send the right codes to ur frontend. hope this helps!

I’ve encountered this issue before, and it can be tricky with GraphQL. The key is to intercept the response before it’s sent back to the client. One effective approach is to use a custom formatError function in your GraphQL setup.

In your Express app, when configuring GraphQL, you can add a formatError function:

app.use('/graphql', createHandler({
  schema,
  formatError: (error) => {
    const originalError = error.originalError;
    if (originalError && originalError.statusCode) {
      res.status(originalError.statusCode);
    }
    return error;
  },
}));

This allows you to set the status code based on your custom error object. In your resolvers, throw errors with a statusCode property:

throw { message: 'Conflict detected', statusCode: 409 };

This method has worked well for me in production. It maintains GraphQL’s error structure while allowing proper HTTP status codes.

hmm, interesting problem! have u tried using a custom error class? something like:

class CustomError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}

then in ur resolvers:
throw new CustomError(‘oops!’, 409);

might that work? what do u think?