Actix-web uses its own [`actix_web::error::Error`][actixerror] type and [`actix_web::error::ResponseError`][responseerror] trait for error handling from web handlers.
If a handler returns an `Error` (referring to the [general Rust trait `std::error::Error`][stderror]) in a `Result` that also implements the `ResponseError` trait, actix-web will render that error as an HTTP response with its corresponding [`actix_web::http::StatusCode`][status_code]. An internal server error is generated by default:
Actix-web provides `ResponseError` implementations for some common non-actix errors. For example, if a handler responds with an `io::Error`, that error is converted into an `HttpInternalServerError`:
`ResponseError` has a default implementation for `error_response()` that will render a _500_ (internal server error), and that's what will happen when the `index` handler executes above.
Actix-web provides a set of error helper functions that are useful for generating specific HTTP error codes from other errors. Here we convert `MyError`, which doesn't implement the `ResponseError` trait, to a _400_ (bad request) using `map_err`:
Actix logs all errors at the `WARN` log level. If an application's log level is set to `DEBUG` and `RUST_BACKTRACE` is enabled, the backtrace is also logged. These are configurable with environmental variables:
The `Error` type uses the cause's error backtrace if available. If the underlying failure does not provide a backtrace, a new backtrace is constructed pointing to the point where the conversion occurred (rather than the origin of the error).
It might be useful to think about dividing the errors an application produces into two broad groups: those which are intended to be user-facing, and those which are not.
An example of the former is that I might use failure to specify a `UserError` enum which encapsulates a `ValidationError` to return whenever a user sends bad input:
However, sending back an error's message isn't desirable for all errors -- there are many failures that occur in a server environment where we'd probably want the specifics to be hidden from the user. For example, if a database goes down and client libraries start producing connect timeout errors, or if an HTML template was improperly formatted and errors when rendered. In these cases, it might be preferable to map the errors to a generic error suitable for user consumption.
By dividing errors into those which are user facing and those which are not, we can ensure that we don't accidentally expose users to errors thrown by application internals which they weren't meant to see.