nautilus_architect_ax/
error.rs1use std::time::Duration;
23
24use nautilus_network::http::HttpClientError;
25use thiserror::Error;
26
27#[derive(Debug, Error)]
29pub enum AxError {
30 #[error("Retryable error: {source}")]
32 Retryable {
33 #[source]
34 source: AxRetryableError,
35 retry_after: Option<Duration>,
37 },
38
39 #[error("Non-retryable error: {source}")]
41 NonRetryable {
42 #[source]
43 source: AxNonRetryableError,
44 },
45
46 #[error("Fatal error: {source}")]
48 Fatal {
49 #[source]
50 source: AxFatalError,
51 },
52
53 #[error("Network error: {0}")]
55 Network(#[from] HttpClientError),
56
57 #[error("WebSocket error: {0}")]
59 WebSocket(String),
60
61 #[error("JSON error: {message}")]
63 Json {
64 message: String,
65 raw: Option<String>,
67 },
68
69 #[error("Configuration error: {0}")]
71 Config(String),
72}
73
74#[derive(Debug, Error)]
76pub enum AxRetryableError {
77 #[error("Rate limit exceeded (remaining: {remaining:?}, reset: {reset_at:?})")]
79 RateLimit {
80 remaining: Option<u32>,
81 reset_at: Option<Duration>,
82 },
83
84 #[error("Service temporarily unavailable")]
86 ServiceUnavailable,
87
88 #[error("Gateway timeout")]
90 GatewayTimeout,
91
92 #[error("Server error (status: {status})")]
94 ServerError { status: u16 },
95
96 #[error("Request timed out after {duration:?}")]
98 Timeout { duration: Duration },
99
100 #[error("Connection failed: {reason}")]
102 ConnectionFailed { reason: String },
103}
104
105#[derive(Debug, Error)]
107pub enum AxNonRetryableError {
108 #[error("Bad request: {message}")]
110 BadRequest { message: String },
111
112 #[error("Authentication failed: {message}")]
114 Unauthorized { message: String },
115
116 #[error("Access forbidden: {message}")]
118 Forbidden { message: String },
119
120 #[error("Resource not found: {message}")]
122 NotFound { message: String },
123
124 #[error("Invalid API response: {message}")]
126 InvalidResponse { message: String },
127
128 #[error("Invalid parameters: {message}")]
130 InvalidParameters { message: String },
131
132 #[error("Order rejected: {message}")]
134 OrderRejected { message: String },
135
136 #[error("Insufficient funds: {message}")]
138 InsufficientFunds { message: String },
139}
140
141#[derive(Debug, Error)]
143pub enum AxFatalError {
144 #[error("Invalid or missing API credentials")]
146 InvalidCredentials,
147
148 #[error("Account suspended: {reason}")]
150 AccountSuspended { reason: String },
151
152 #[error("Configuration error: {message}")]
154 SystemMisconfiguration { message: String },
155
156 #[error("Unrecoverable parsing error: {message}")]
158 ParseError { message: String },
159}
160
161impl AxError {
162 #[must_use]
164 pub fn is_retryable(&self) -> bool {
165 matches!(self, Self::Retryable { .. })
166 }
167
168 #[must_use]
170 pub fn is_fatal(&self) -> bool {
171 matches!(self, Self::Fatal { .. })
172 }
173
174 #[must_use]
176 pub fn json_parse(message: impl Into<String>, raw: Option<String>) -> Self {
177 Self::Json {
178 message: message.into(),
179 raw,
180 }
181 }
182
183 #[must_use]
185 pub fn websocket(message: impl Into<String>) -> Self {
186 Self::WebSocket(message.into())
187 }
188
189 #[must_use]
191 pub fn config(message: impl Into<String>) -> Self {
192 Self::Config(message.into())
193 }
194}