Skip to main content

papers_openalex/
error.rs

1/// Errors returned by [`OpenAlexClient`](crate::OpenAlexClient) methods.
2///
3/// # Variants
4///
5/// - [`Http`](OpenAlexError::Http) — network or connection failure (wraps
6///   [`reqwest::Error`])
7/// - [`Json`](OpenAlexError::Json) — response body could not be deserialized
8///   (wraps [`serde_json::Error`])
9/// - [`Api`](OpenAlexError::Api) — the OpenAlex API returned a non-success HTTP
10///   status code (e.g. 404 for unknown entity, 403 for forbidden, 500 for
11///   server error)
12///
13/// # Example
14///
15/// ```no_run
16/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
17/// use papers_openalex::{OpenAlexClient, GetParams, OpenAlexError};
18///
19/// let client = OpenAlexClient::new();
20/// match client.get_work("nonexistent", &GetParams::default()).await {
21///     Ok(work) => println!("Found: {}", work.id),
22///     Err(OpenAlexError::Api { status, message }) => {
23///         eprintln!("API error {status}: {message}");
24///     }
25///     Err(e) => eprintln!("Other error: {e}"),
26/// }
27/// # Ok(())
28/// # }
29/// ```
30#[derive(Debug, thiserror::Error)]
31pub enum OpenAlexError {
32    /// Network or connection error from reqwest.
33    #[error("HTTP error: {0}")]
34    Http(#[from] reqwest::Error),
35
36    /// Failed to deserialize the JSON response body.
37    #[error("JSON error: {0}")]
38    Json(#[from] serde_json::Error),
39
40    /// The API returned a non-success HTTP status code.
41    ///
42    /// `status` is the HTTP status code (e.g. 404, 403, 500) and `message`
43    /// contains the response body text.
44    #[error("API error (status {status}): {message}")]
45    Api { status: u16, message: String },
46}
47
48/// A [`Result`](std::result::Result) alias with [`OpenAlexError`] as the error
49/// type.
50pub type Result<T> = std::result::Result<T, OpenAlexError>;