Skip to main content

MatrixApiError

Derive Macro MatrixApiError 

Source
#[derive(MatrixApiError)]
{
    // Attributes available to this derive:
    #[matrix_api_error]
}
Expand description

Re-export the MatrixApiError derive macro here, so one just needs to depend on arminius-lib-component when implementing MatrixApiErrors. Implements the traits arminius_lib_component::error::MatrixApiError and [axum::response::IntoResponse] for the struct or enum. Errors can be defined on structs or on enums

§Structs

To implement simple individual errors, we implement them as structs. This requires that the type on which we’re deriving MatrixApiError implements [ToString], which can conveniently be done through the thiserror crate. To implement it, you give the attribute #[matrix_api_error] with two arguments, status_code which is a [axum::http::StatusCode] and error_kind which is an [ruma::api::error::ErrorKind] value.

§Example

To implement an InvalidUserId error, which can also be printed as a matrix error, we use the proc macro to derive arminius_lib_component::error::MatrixApiError:

#[derive(thiserror::Error, MatrixApiError, Debug)]
#[error("Invalid user id: {0}")]
#[matrix_api_error(status_code = StatusCode::BAD_REQUEST, error_kind = ErrorKind::BadJson)]
struct InvalidUserId(String);

This will cause InvalidUserId to implement MatrixApiError in such a way that InvalidUserId("jens".to_owned)::create_matrix_error() will result in:

{
  "errcode": "M_BAD_JSON",
  "error": "Invalid user id: jens"
}

And converting it into a response with [axum::response::IntoResponse::into_response] will give a return code 400, with the above body

§Enums

For cases where we want to describe several possible errors we use an enum which can collect several other errors, but also define their own errors where applicable. Each variant of the enum must either have exactly one field which implements MatrixApiError, usually with the help of this macro, or have the attribute #[matrix_api_error] to define the matrix api error inline.

§Example

#[derive(thiserror::Error, MatrixApiError, Debug)]
#[error("Invalid user id: {0}")]
#[matrix_api_error(status_code = StatusCode::BAD_REQUEST, error_kind = ErrorKind::BadJson)]
struct InvalidUserId(String);

#[derive(thiserror::Error, Debug, MatrixApiError)]
enum LoginError {
   #[error(transparent)]
   InvalidUsername(#[from] InvalidUserId),

   #[error("Incorrect password for user. The actual password is {0}")]
   #[matrix_api_error(status_code = StatusCode::UNAUTHORIZED, error_kind =
       ErrorKind::Forbidden)]
   IncorrectPassword(String),
}

This will implement MatrixApiError and IntoResponse in such a way that LoginError::InvalidUsername will use the implementation of MatrixApiError implemented by the InvalidUserId type, whereas IncorrectPassword will create a matrix api error with the status code UNAUTHORIZED and error kind FORBIDDEN.

Note that this derive macro is re-exported from arminius_lib_component, so that it is sufficient to just depend on arminius_lib_component instead of depending on arminius-lib-macros directly. This is also the reason for the funny name with the two dashes.