Apollo-server: Format Error: no error message displayed

Created on 8 Aug 2018  路  9Comments  路  Source: apollographql/apollo-server

I'm trying to format errors following this example from the docs:

const server = new ApolloServer({ typeDefs, resolvers, formatError: error => { console.log(error); return new Error('Custom Error Message'); }, });

The error logs correctly but on the response I'm getting

"errors": [ {} ]

If I use:
return new ApolloError('Custom Error Message', 'somecode');
I get:
"errors": [ { "extensions": { "code": "somecode" } } ]

If I use
return new AuthenticationError('Some error');
I get:
"errors": [ { "extensions": { "code": "UNAUTHENTICATED" } } ]

Without the "formatError" everything reports fine.
I also tried importing from _apollo-server_ instead of _apollo-server-express_ but I get the same results.

I'm using:
_"apollo-server-express": "2.0.0",
"graphql": "0.13.2",_

Most helpful comment

It seems to be fixed by simply changing the super call to the following:

super(message, undefined, undefined, undefined, undefined, undefined,  { "code": code });

And then removing Line 35
And presumably line 4 is no longer used.

Perhaps @martijnwalraven or @evans can shed some light on the implementation of the ApolloError class?

For reference, I have implemented my own much smaller variant to support just exposing the error code and message in the response:

class BaseErrorApolloError extends GraphQLError {

  constructor(message: string, code?: string) {
    super(message, undefined, undefined, undefined, undefined, undefined, {
      code: code
    });
  }
}

I use this as a "catch all" error returned from the formatError function in ApolloServer.
This returns both returns a message and an extension object contain a "code" property with the specified code.

Perhaps @dimpen have some use for it.

All 9 comments

I have a similar issue in TypeScript. It seems like the ApolloError does not implement GraphQLError properly because if you instead throw a GraphQLError you can make the message display.
However, this does not seem like a nice solution.

It seems that the issue is with this line of code inside of the ApolloError class:
this.extensions = { code };
On line 35.

It throws the following exception in TypeScript:
TypeError: Cannot assign to read only property 'extensions' of object 'GraphQLError:

Which is because the extensions property in GraphQLError is a readonly property.
It seems that in TypeScript you are not able to "overload" a property, just like you can not overload a method.

It seems to be fixed by simply changing the super call to the following:

super(message, undefined, undefined, undefined, undefined, undefined,  { "code": code });

And then removing Line 35
And presumably line 4 is no longer used.

Perhaps @martijnwalraven or @evans can shed some light on the implementation of the ApolloError class?

For reference, I have implemented my own much smaller variant to support just exposing the error code and message in the response:

class BaseErrorApolloError extends GraphQLError {

  constructor(message: string, code?: string) {
    super(message, undefined, undefined, undefined, undefined, undefined, {
      code: code
    });
  }
}

I use this as a "catch all" error returned from the formatError function in ApolloServer.
This returns both returns a message and an extension object contain a "code" property with the specified code.

Perhaps @dimpen have some use for it.

@Nift
I'm now using "apollo-server-express": "2.0.5" and I'm seeing this class:

export class ApolloError extends Error implements GraphQLError

the Error refers to @types/graphql/index.d.ts:
interface Error { stack?: string; }

So to make your super signature work I changed it to
export class ApolloError extends GraphQLError
to refer to the super of GraphQLError with that signature.

BTW I think that any association of the ApolloError class with Error is redundant and confusing and should be avoided. GraphQLError extends 'Error' anyway.
But if I'm missing something and this is needed, Error should be implemented not extended. So it should be:
export class ApolloError extends GraphQLError implements Error

I also removed lines 4, 35 and recompiled.

So I'm originally throwing a ForbiddenError and then I format it in formatError with a different message and code
return new ApolloError('Custom Error Message', 'somecode');

So now in the graphql response I get the custom error message but the extensions with the code are empty.
"errors": [ { "message": "Custom Error Message" } ]

Are you getting both the message and the code?
What apollo and graphql versions and packages are you on?

@dimpen I am unsure how exactly your code looks like, however, what solved the issue for me is basically calling the GraphQLError class' constructor as above and then feed the code in properly:

super(message, undefined, undefined, undefined, undefined, undefined, {
      code: code
    });

The class I described earlier returns both a message and a code properly.

I was using the apollo-server-express library as well when solving this issue, but the Apollo Error is part of the apollo-server project and not the express add-on.

@dimpen you said:

Without the "formatError" everything reports fine.

Though I am not seeing an error message in a specific case, whether I use formatError or not.

I have this Express error handler:

app.use((err, req, res, next) => {
  logger.error(err);
  if (process.env.NODE_ENV === "development") {
    res.status(500).send(err);
  } else {
    res.status(500).send("Internal Server Error.");
  }
});

But if I throw an error in the passport validation middleware, the error gets sent to the user in HTML instead of in JSON. Is there something I could be missing?

Here is the solution, I think that you need to "cast" (actually, enrich or internally add some props) again (it's something already done before formatError) ApolloError to GraphQLError, one way to do this is by using the apollo-server-core formatApolloErrors method:

import { formatApolloErrors } from 'apollo-server-core';
//...
formatError: (error: GraphQLError): GraphQLFormattedError => {
    const formattedError = new ApolloError('Example message', 'EXAMPLE_CODE');
    return formatApolloErrors([formattedError])[0];
}

Thank you for reporting this! It appears to be resolved so I'm going to close the issue. If you're still running into problems please feel free to reopen the issue.

@caydie-tran are there any plans for a formatError function in Apollo Client (analogous to the Apollo Server option)? it would be nice to be able to format the error before it is received at the consumer

I noticed this in 2.4.8, and it's fixed in current (2.6.9)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danilobuerger picture danilobuerger  路  3Comments

leinue picture leinue  路  3Comments

deathg0d picture deathg0d  路  3Comments

jpcbarros picture jpcbarros  路  3Comments

mathroc picture mathroc  路  3Comments