If I throw an AuthenticationError from a resolver, I cannot detect this from the formatError handler. For example:
// somewhere in a resolver...
import { AuthenticationError } from 'apollo-server-express'
const resolve = (_, args, context) => {
throw new AuthenticationError('test')
}
// in formatError handler
const formatError = (error) => {
console.log(error instanceof AuthenticationError) // returns false
return error
}
HOWEVER, if the error is SyntaxError or ValidationError produced by GraphQL automatically due to a malformatted graphql request, then the instanceof check works.
A quick working sample: https://codesandbox.io/s/apollo-server-ft3ul?fontsize=14
as an aside, my use case is i want to use the instanceof check to handle specific errors in the formatError handler based on the type of error (ie. for logging purposes).
if for some reason its impossible to preserve the error type, then exporting a static list of the different error codes produced by apollo's errors would be useful so i could check based on those as an alternate route
Same for me, it just returns GraphQLError for everything. My version is 2.6.4. But I believe this bug also works since versions ^2.4.8.
Have you tried checking error.originalError?
@bnaoki Thanks, it works. But I think it should be stated somewhere in docs.
@kabachook @bnaoki when i use instanceof on error.originalError it still doesnt preserve the original error type thrown (or at least i am unable to reproduce it)
@stringbeans following your example, I changed error to error.originalError and it worked. On CodeSandbox it is an old version of apollo-server, try upgrading it.
I am having this same issue, even with error.originalError
I am using TypeORM which will throw a QueryFailedError when a query Timeout occurs (along the lines of QueryFailedError: Error: Timeout: Request failed to complete in 5000ms).
This is the correct instance in the resolver, but when it reaches formatError it seems to have been mutated. Note, I don't have any plugins on the server.
// within resolver
{
...
try {
const typeORMResult = await query.getMany();
return typeORMResult;
} catch (e) {
console.log(e.name); // logs 'QueryFailedError'
console.log(e instanceof QueryFailedError); // logs 'true'
throw e;
}
...
}
// formatError
formatError: err => {
console.log(err.originalError.name); // logs 'Error'
console.log(err.originalError instanceof QueryFailedError); // logs 'false'
console.log(err.originalError instanceof Error); // logs 'true'
return err;
},
Additional: If I create an apollo plugin and hook in to didEncounterErrors the same thing happens. The originalError here is also no longer a QueryFailedError
(This is all in [email protected])
Interestingly, if an ApolloError is thrown from the Resolver it seems to preserve the Error type, but not if any custom errors are thrown. Some more snippets..
A custom error
export class CustomError extends Error {}
// within resolver
try {
const cargoes = await query.getMany();
return convertColumns(cargoes);
} catch (e) {
const E = new CustomError('Boo');
console.log(E instanceof CustomError); // logs 'true'
throw e;
}
// within formatError
formatError: err => {
console.log(err.originalError instanceof CustomError); // logs 'false'
return err;
},
An ApolloError
// within resolver
try {
const cargoes = await query.getMany();
return convertColumns(cargoes);
} catch (e) {
throw new ApolloError('Foo');
}
// within formatError
formatError: err => {
console.log(err.originalError instanceof ApolloError); // logs 'true'
return err;
},
Most helpful comment
Have you tried checking
error.originalError?