diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 1ff86049fc..3390b7490f 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -307,6 +307,7 @@ const sidebar = { ] }, ['/developer-docs/latest/developer-resources/cli/CLI', 'Command Line Interface'], + ['/developer-docs/latest/developer-resources/error-handling.md', 'Error handling'], ], }, { diff --git a/docs/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.md b/docs/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.md index f1c476ff6f..d2f17c7ab4 100644 --- a/docs/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.md +++ b/docs/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.md @@ -20,6 +20,8 @@ Responses are unified with the GraphQL API in that: - queries and mutations that return information for a single entry mainly use a `XxxEntityResponse` type - queries and mutations that return i️nformation for multiple entries mainly use a `XxxEntityResponseCollection` type, which includes `meta` information (with [pagination](#pagination)) in addition to the data itself +Responses can also include an `error` (see [error handling documentation](/developer-docs/latest/developer-resources/error-handling.md)). + ::: details Example: Response formats for queries and mutations with an example 'Article' content-type ```graphql diff --git a/docs/developer-docs/latest/developer-resources/database-apis-reference/rest-api.md b/docs/developer-docs/latest/developer-resources/database-apis-reference/rest-api.md index e9a4465b17..0922947e4a 100644 --- a/docs/developer-docs/latest/developer-resources/database-apis-reference/rest-api.md +++ b/docs/developer-docs/latest/developer-resources/database-apis-reference/rest-api.md @@ -145,7 +145,7 @@ Whatever the query, the response is always an object with the following keys: - `meta`(object): information about pagination, publication state, available locales, etc. -- `error` (object, _optional_): information about any error thrown by the request +- `error` (object, _optional_): information about any [error](/developer-docs/latest/developer-resources/error-handling.md) thrown by the request ### Get entries diff --git a/docs/developer-docs/latest/developer-resources/error-handling.md b/docs/developer-docs/latest/developer-resources/error-handling.md new file mode 100644 index 0000000000..68fee1afa3 --- /dev/null +++ b/docs/developer-docs/latest/developer-resources/error-handling.md @@ -0,0 +1,94 @@ +--- +title: Error handling - Strapi Developer Documentation +description: … +--- + + + +# Error handling + +Strapi is natively handling errors with a standard format. + +There are 2 use cases for error handling: + +- As a developer querying content through the [REST](/developer-docs/latest/developer-resources/database-apis-reference/rest-api.md) or [GraphQL](/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.md) APIs, you might [receive errors](#receiving-errors) in response to the requests. +- As a developer customizing the backend of your Strapi application, you could use controllers and services to [throw errors](#throwing-errors). + +## Receiving errors + +Errors are included in the response object with the `error` key and include information such as the HTTP status code, the name of the error, and additional information. + +### REST errors + +Errors thrown by the REST API are included in the [response](/developer-docs/latest/developer-resources/database-apis-reference/rest-api.html#unified-response-format) that has the following format: + +```json +{ + "data": null, + "error": { + "status": "", // HTTP status + "name": "", // Strapi error name ('ApplicationError' or 'ValidationError') + "message": "", // A human reable error message + "details": { + // error info specific to the error type + } + } +} +``` + + + +### GraphQL errors + +Errors thrown by the GraphQL API are included in the [response](/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.html#unified-response-format) that has the following format: + +```json +{ "errors": [ + { + "message": "", // A human reable error message + "extensions": { + "error": { + "name": "", // Strapi error name ('ApplicationError' or 'ValidationError'), + "message": "", // A human reable error message (same one as above); + "details": {}, // Error info specific to the error type + }, + "code": "" // GraphQL error code (ex: BAD_USER_INPUT) + } + } + ], + "data": { + "graphQLQueryName": null + } +} +``` + +## Throwing errors + +The recommended way to throw errors when developing any custom logic with Strapi is to have the [controller](/developer-docs/latest/development/backend-customization/controllers.md) respond with the correct status and body. + +This can be done by calling an error function on the context (i.e. `ctx`). Available error functions are listed in the [http-errors documentation](https://github.com/jshttp/http-errors#list-of-all-constructors) but their name should be camel-cased to be used by Strapi (e.g. `badRequest`). + +Error functions accept 2 parameters that correspond to the `error.message` and `error.details` attributes [received](#receiving-errors) by a developer querying the API: + +- the first parameter of the function is the error `message` +- and the second one is the object that will be set as `details` in the response received + +```js + +// path: ./src/api/[api-name]/controllers/my-controller.js + +module.exports = { + renameDog: async (ctx, next) => { + const newName = ctx.request.body.name; + if (!newName) { + return ctx.badRequest('name is missing', { foo: 'bar' }) + } + ctx.body = strapi.service('api::dog.dog').rename(newName); + } +} + +``` + +:::note +[Services](/developer-docs/latest/development/backend-customization/services.md) don't have access to the controller's `ctx` object. If services need to throw errors, these need to be caught by the controller, that in turn is in charge of calling the proper error function. +:::