apollo-server/docs/source/features/errors.md

125 lines
3.9 KiB
Markdown
Raw Normal View History

2018-05-02 11:19:14 -07:00
---
title: Error handling
description: Making errors actionable on the client and server
---
2018-05-02 11:46:29 -07:00
Apollo server provides a couple predefined errors, including `AuthenticationError`, `ForbiddenError`, and a generic `ApolloError`. These errors are designed to enhance errors thrown before and during GraphQL execution. The provided errors focus on debugging a Apollo server as well as enabling the client to take specific action based on an error.
2018-05-02 11:19:14 -07:00
2018-05-02 11:46:29 -07:00
When an error occurs in Apollo server both inside and outside of resolvers, each error inside of the `errors` array will contain an object at `extensions` that contains the information added by Apollo server.
2018-05-02 11:19:14 -07:00
## Default information
The first step to improving the usability of a server is providing the error stack trace by default. The following example demonstrates the response returned from Apollo server with a resolver that throws a node [`SystemError`](https://nodejs.org/api/errors.html#errors_system_errors).
```js line=14-16
2018-05-02 11:19:14 -07:00
const {
ApolloServer,
gql,
} = require('apollo-server');
const typeDefs = gql`
type Query {
readError: String
}
`;
const resolvers = {
Query: {
2018-05-02 11:32:04 -07:00
readError: (parent, args, context) => {
2018-05-02 11:19:14 -07:00
fs.readFileSync('/does/not/exist');
},
},
};
```
The response will return:
![Screenshot demonstrating an error stacktrace and additional](../images/features/error-stacktrace.png)
> To disable stacktraces for production, pass `debug: false` to the Apollo server constructor or set the `NODE_ENV` environment variable to 'production' or 'test'
## Codes
In addition to stacktraces, Apollo Server's exported errors specify a human-readable string in the `code` field of `extensions` that enables the client to perform corrective actions. In addition to improving the client experience, the `code` field allows the server to categorize errors. For example, an `AuthenticationError` sets the code to `UNAUTHENTICATED`, which enables the client to reauthenticate and would generally be ignored as a server anomaly.
```js line=4,15-17
const {
ApolloServer,
gql,
AuthenticationError,
} = require('apollo-server');
const typeDefs = gql`
type Query {
authenticationError: String
}
`;
const resolvers = {
Query: {
2018-05-02 11:32:04 -07:00
authenticationError: (parent, args, context) => {
2018-05-02 11:19:14 -07:00
throw AuthenticationError('must authenticate');
},
},
};
```
The response will return:
![Screenshot demonstrating unauthenticated error code](../images/features/error-code.png)
## Augmenting error details
`ApolloError` can be augmented with additional information when the default information requires more context. This information could include a localized message that should be displayed to the user on an error or in the case of bad input a description of the fields that are invalid. The following example demonstrates adding extra information to a user input check.
```js line=14-20
2018-05-02 11:19:14 -07:00
const {
ApolloServer,
2018-06-01 21:32:57 +01:00
ApolloError,
2018-05-02 11:19:14 -07:00
gql,
} = require('apollo-server');
const typeDefs = gql`
type Mutation {
userInputError(input: String): String
}
`;
const resolvers = {
Mutation: {
2018-05-02 11:32:04 -07:00
userInputError: (parent, args, context, info) => {
2018-05-02 11:19:14 -07:00
if(args.input !== 'expected') {
throw ApolloError('Form Arguments invalid', 'BAD_USER_INPUT', {
invalidArgs: Object.keys(args),
});
}
},
},
};
```
The response will return:
![Screenshot demonstrating augmented error](../images/features/error-user-input.png)
## Masking and logging errors
The Apollo server constructor accepts a `formatError` function that is run on each error passed back to the client. This can be used to mask errors as well as logging.
This example demonstrates masking
```js line=4-7
const server = new ApolloServer({
typeDefs,
resolvers,
formatError: error => {
console.log(error);
return new Error('Internal server error');
},
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
```