questrade_client/error.rs
1//! Error types for the questrade-client crate.
2
3use reqwest::StatusCode;
4
5/// Errors returned by the Questrade API client.
6#[derive(Debug, thiserror::Error)]
7pub enum QuestradeError {
8 /// An HTTP/network error from the underlying `reqwest` client.
9 #[error("HTTP request failed: {0}")]
10 Http(#[from] reqwest::Error),
11
12 /// The Questrade API returned a non-success status code.
13 #[error("Questrade API error ({status}): {body}")]
14 Api {
15 /// HTTP status code returned by the API.
16 status: StatusCode,
17 /// Response body (may contain a JSON error object or plain text).
18 body: String,
19 },
20
21 /// Rate-limited (HTTP 429) after exhausting all retry attempts.
22 #[error("Questrade API rate limit exceeded after {retries} retries")]
23 RateLimited {
24 /// Number of retry attempts made before giving up.
25 retries: u32,
26 },
27
28 /// OAuth token refresh failed with a non-success status.
29 #[error("Token refresh failed ({status}): {body}")]
30 TokenRefresh {
31 /// HTTP status code from the auth server.
32 status: StatusCode,
33 /// Response body from the auth server.
34 body: String,
35 },
36
37 /// Failed to deserialize a JSON response body.
38 #[error("Failed to parse response: {0}")]
39 Deserialization(#[from] serde_json::Error),
40
41 /// A datetime string could not be formatted or parsed.
42 #[error("{context}: {source}")]
43 DateTime {
44 /// What we were trying to do (e.g. "Failed to parse datetime: …").
45 context: String,
46 /// The underlying `time` format or parse error.
47 source: Box<dyn std::error::Error + Send + Sync>,
48 },
49
50 /// A symbol lookup returned no matching result.
51 #[error("Symbol not found: {0}")]
52 SymbolNotFound(String),
53
54 /// A response was expected to contain at least one item but was empty.
55 #[error("{0}")]
56 EmptyResponse(String),
57}
58
59/// Convenience type alias for `Result<T, QuestradeError>`.
60pub type Result<T> = std::result::Result<T, QuestradeError>;