Skip to main content

bybit/
error.rs

1#[derive(Debug)]
2pub enum Error {
3    Api {
4        code: i64,
5        msg: String,
6    },
7    /// A non-2xx HTTP response whose body is not a Bybit error envelope
8    /// (e.g. an HTML page from a CDN or gateway). `body` may be truncated.
9    Http {
10        status: u16,
11        body: String,
12    },
13    InvalidHeaderValue(reqwest::header::InvalidHeaderValue),
14    Io(std::io::Error),
15    /// A private endpoint was called on a client created without
16    /// `api_key`/`api_secret`.
17    MissingCredentials,
18    Msg(String),
19    /// The local rate limiter rejected the request before it was sent.
20    /// `retry_after_ms` is the estimated wait until capacity is available.
21    RateLimited {
22        retry_after_ms: u64,
23    },
24    /// The local rate limiter can never let this request through: its cost
25    /// exceeds the bucket's burst, or the bucket does not refill. Retrying
26    /// will not help; adjust [`RateLimiterConfig`](crate::http::RateLimiterConfig).
27    RateLimitUnsatisfiable {
28        cost: u32,
29        burst: u32,
30    },
31    Reqwest(reqwest::Error),
32    SerdeJson(serde_json::Error),
33    /// A `*_all` pagination helper fetched `max` pages without reaching the end.
34    TooManyPages {
35        max: usize,
36    },
37    SerdeUrlEncoded(serde_urlencoded::ser::Error),
38    SerdePathToError(serde_path_to_error::Error<serde_json::Error>),
39}
40
41impl std::fmt::Display for Error {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        match self {
44            Error::Api { code, msg } => write!(f, "Bybit API error: code: {code}, message: {msg}"),
45            Error::Http { status, body } => write!(f, "HTTP error: status: {status}, body: {body}"),
46            Error::InvalidHeaderValue(error) => write!(f, "invalid header value: {error}"),
47            Error::Io(error) => write!(f, "I/O error: {error}"),
48            Error::MissingCredentials => {
49                write!(
50                    f,
51                    "api_key and api_secret are required for private endpoints"
52                )
53            }
54            Error::Msg(msg) => write!(f, "{msg}"),
55            Error::RateLimited { retry_after_ms } => {
56                write!(f, "rate limited: retry after {retry_after_ms} ms")
57            }
58            Error::RateLimitUnsatisfiable { cost, burst } => write!(
59                f,
60                "rate limit can never be satisfied: request cost {cost}, bucket burst {burst}"
61            ),
62            Error::Reqwest(error) => write!(f, "reqwest error: {error}"),
63            Error::TooManyPages { max } => {
64                write!(f, "pagination did not finish after {max} pages")
65            }
66            Error::SerdeJson(error) => write!(f, "serde_json error: {error}"),
67            Error::SerdeUrlEncoded(error) => write!(f, "serde_urlencoded error: {error}"),
68            Error::SerdePathToError(error) => write!(
69                f,
70                "serde_path_to_error error: path: {}, msg: {}",
71                error.path(),
72                error.inner()
73            ),
74        }
75    }
76}
77
78impl std::error::Error for Error {
79    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
80        match self {
81            Error::InvalidHeaderValue(error) => Some(error),
82            Error::Io(error) => Some(error),
83            Error::Reqwest(error) => Some(error),
84            Error::SerdeJson(error) => Some(error),
85            Error::SerdeUrlEncoded(error) => Some(error),
86            Error::SerdePathToError(error) => Some(error),
87            Error::Api { .. }
88            | Error::Http { .. }
89            | Error::MissingCredentials
90            | Error::Msg(_)
91            | Error::RateLimited { .. }
92            | Error::RateLimitUnsatisfiable { .. }
93            | Error::TooManyPages { .. } => None,
94        }
95    }
96}
97
98impl From<std::io::Error> for Error {
99    fn from(err: std::io::Error) -> Self {
100        Error::Io(err)
101    }
102}
103
104impl From<String> for Error {
105    fn from(msg: String) -> Self {
106        Error::Msg(msg)
107    }
108}
109
110impl From<&str> for Error {
111    fn from(msg: &str) -> Self {
112        Error::Msg(msg.to_string())
113    }
114}
115
116impl From<super::http::APIErrorResponse> for Error {
117    fn from(resp: super::http::APIErrorResponse) -> Self {
118        Self::Api {
119            code: resp.ret_code,
120            msg: resp.ret_msg,
121        }
122    }
123}
124
125impl From<reqwest::header::InvalidHeaderValue> for Error {
126    fn from(err: reqwest::header::InvalidHeaderValue) -> Self {
127        Error::InvalidHeaderValue(err)
128    }
129}
130
131impl From<reqwest::Error> for Error {
132    fn from(err: reqwest::Error) -> Self {
133        Error::Reqwest(err)
134    }
135}
136
137impl From<serde_json::Error> for Error {
138    fn from(err: serde_json::Error) -> Self {
139        Error::SerdeJson(err)
140    }
141}
142
143impl From<serde_urlencoded::ser::Error> for Error {
144    fn from(err: serde_urlencoded::ser::Error) -> Self {
145        Error::SerdeUrlEncoded(err)
146    }
147}
148
149impl From<serde_path_to_error::Error<serde_json::Error>> for Error {
150    fn from(err: serde_path_to_error::Error<serde_json::Error>) -> Self {
151        Error::SerdePathToError(err)
152    }
153}