Skip to main content

canvas_lms_api/
error.rs

1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum CanvasError {
5    #[error("Bad request: {message}")]
6    BadRequest {
7        message: String,
8        errors: Vec<ApiError>,
9    },
10
11    #[error("Invalid access token: {0}")]
12    InvalidAccessToken(String),
13
14    #[error("Unauthorized: {0}")]
15    Unauthorized(String),
16
17    #[error("Forbidden: {0}")]
18    Forbidden(String),
19
20    #[error("Resource does not exist")]
21    ResourceDoesNotExist,
22
23    #[error("Conflict: {0}")]
24    Conflict(String),
25
26    #[error("Unprocessable entity: {0}")]
27    UnprocessableEntity(String),
28
29    #[error("Rate limit exceeded (X-Rate-Limit-Remaining: {remaining:?})")]
30    RateLimitExceeded { remaining: Option<String> },
31
32    #[error("Canvas API error (status {status}): {message}")]
33    ApiError { status: u16, message: String },
34
35    #[error(transparent)]
36    Http(#[from] reqwest::Error),
37
38    #[error(transparent)]
39    Json(#[from] serde_json::Error),
40
41    #[error(transparent)]
42    Url(#[from] url::ParseError),
43
44    #[error(transparent)]
45    Io(#[from] std::io::Error),
46}
47
48#[derive(Debug, Clone, serde::Deserialize)]
49pub struct ApiError {
50    pub message: Option<String>,
51    #[serde(rename = "type")]
52    pub error_type: Option<String>,
53}
54
55#[derive(Debug, serde::Deserialize)]
56pub(crate) struct CanvasErrorBody {
57    pub errors: Option<Vec<ApiError>>,
58    pub error: Option<String>,
59    #[allow(dead_code)] // surfaced in future error reporting
60    pub error_report_id: Option<u64>,
61}
62
63pub type Result<T> = std::result::Result<T, CanvasError>;