1use error_support::{ErrorHandling, GetErrorHandling};
6use std::string;
7
8#[derive(Debug, thiserror::Error)]
13pub enum FxaError {
14 #[error("authentication error")]
19 Authentication,
20 #[error("forbidden")]
25 Forbidden,
26 #[error("network error")]
29 Network,
30 #[error("no authentication flow was active")]
36 NoExistingAuthFlow,
37 #[error("the requested authentication flow was not active")]
45 WrongAuthFlow,
46 #[error("Origin mismatch")]
51 OriginMismatch,
52 #[error("The sync scoped key was missing")]
54 SyncScopedKeyMissingInServerResponse,
55 #[error("panic in native code")]
59 Panic,
60 #[error("other error: {0}")]
62 Other(String),
63}
64
65#[derive(Debug, thiserror::Error)]
68pub enum Error {
69 #[error("Server asked the client to back off, please wait {0} seconds to try again")]
70 BackoffError(u64),
71
72 #[error("Unknown OAuth State")]
73 UnknownOAuthState,
74
75 #[error("No cached scoped keys for scope {0}")]
76 NoScopedKey(String),
77
78 #[error("No stored refresh token")]
79 NoRefreshToken,
80
81 #[error("No stored session token")]
82 NoSessionToken,
83
84 #[error("No stored migration data")]
85 NoMigrationData,
86
87 #[error("No stored current device id")]
88 NoCurrentDeviceId,
89
90 #[error("Device target is unknown (Device ID: {0})")]
91 UnknownTargetDevice(String),
92
93 #[error("Api client error {0}")]
94 ApiClientError(&'static str),
95
96 #[error("Illegal state: {0}")]
97 IllegalState(&'static str),
98
99 #[error("Unknown command: {0}")]
100 UnknownCommand(String),
101
102 #[error("Send Tab diagnosis error: {0}")]
103 SendTabDiagnosisError(&'static str),
104
105 #[error("Cannot xor arrays with different lengths: {0} and {1}")]
106 XorLengthMismatch(usize, usize),
107
108 #[error("Origin mismatch: {0}")]
109 OriginMismatch(String),
110
111 #[error("Remote key and local key mismatch")]
112 MismatchedKeys,
113
114 #[error("The response from the server, or the content in that reponse, was unexpected")]
118 UnexpectedServerResponse,
119
120 #[error("The sync scoped key was missing in the server response")]
124 SyncScopedKeyMissingInServerResponse,
125
126 #[error("Client: {0} is not allowed to request scope: {1}")]
127 ScopeNotAllowed(String, String),
128
129 #[error("Unsupported command: {0}")]
130 UnsupportedCommand(&'static str),
131
132 #[error("Missing URL parameter: {0}")]
133 MissingUrlParameter(&'static str),
134
135 #[error("Null pointer passed to FFI")]
136 NullPointer,
137
138 #[error("Invalid buffer length: {0}")]
139 InvalidBufferLength(i32),
140
141 #[error("Too many calls to auth introspection endpoint")]
142 AuthCircuitBreakerError,
143
144 #[error("Remote server error: '{code}' '{errno}' '{error}' '{message}' '{info}'")]
145 RemoteError {
146 code: u64,
147 errno: u64,
148 error: String,
149 message: String,
150 info: String,
151 },
152
153 #[error("Crypto/NSS error: {0}")]
155 CryptoError(#[from] rc_crypto::Error),
156
157 #[error("http-ece encryption error: {0}")]
158 EceError(#[from] rc_crypto::ece::Error),
159
160 #[error("Hex decode error: {0}")]
161 HexDecodeError(#[from] hex::FromHexError),
162
163 #[error("Base64 decode error: {0}")]
164 Base64Decode(#[from] base64::DecodeError),
165
166 #[error("JSON error: {0}")]
167 JsonError(#[from] serde_json::Error),
168
169 #[error("JWCrypto error: {0}")]
170 JwCryptoError(#[from] jwcrypto::JwCryptoError),
171
172 #[error("UTF8 decode error: {0}")]
173 UTF8DecodeError(#[from] string::FromUtf8Error),
174
175 #[error("Network error: {0}")]
176 RequestError(#[from] viaduct::ViaductError),
177
178 #[error("Malformed URL: {sanitized_url} ({when})")]
179 MalformedUrl {
180 sanitized_url: String,
183 when: String,
184 },
185
186 #[error("Unexpected HTTP status: {0}")]
187 UnexpectedStatus(#[from] viaduct::UnexpectedStatus),
188
189 #[error("Sync15 error: {0}")]
190 SyncError(#[from] sync15::Error),
191
192 #[error("Integer conversion error: {0}")]
193 IntegerConversionError(#[from] std::num::TryFromIntError),
194
195 #[error("Command not found by fxa")]
196 CommandNotFound,
197
198 #[error("Invalid Push Event")]
199 InvalidPushEvent,
200
201 #[error("Invalid state transition: {0}")]
202 InvalidStateTransition(String),
203
204 #[error("Internal error in the state machine: {0}")]
205 StateMachineLogicError(String),
206}
207
208impl GetErrorHandling for Error {
211 type ExternalError = FxaError;
212
213 fn get_error_handling(&self) -> ErrorHandling<Self::ExternalError> {
214 match self {
215 Error::RemoteError { code: 401, .. }
216 | Error::NoRefreshToken
217 | Error::NoSessionToken
218 | Error::NoScopedKey(_) => {
219 ErrorHandling::convert(FxaError::Authentication).log_warning()
220 }
221 Error::RemoteError { code: 403, .. } => {
222 ErrorHandling::convert(FxaError::Forbidden).log_warning()
223 }
224 Error::RequestError(_) => ErrorHandling::convert(FxaError::Network).log_warning(),
225 Error::SyncScopedKeyMissingInServerResponse => {
226 ErrorHandling::convert(FxaError::SyncScopedKeyMissingInServerResponse)
227 .report_error("fxa-client-scoped-key-missing")
228 }
229 Error::UnknownOAuthState => {
230 ErrorHandling::convert(FxaError::NoExistingAuthFlow).log_warning()
231 }
232 Error::BackoffError(_) => ErrorHandling::convert(FxaError::Other(self.to_string()))
233 .report_error("fxa-client-backoff"),
234 Error::InvalidStateTransition(_) | Error::StateMachineLogicError(_) => {
235 ErrorHandling::convert(FxaError::Other(self.to_string()))
236 .report_error("fxa-state-machine-error")
237 }
238 Error::OriginMismatch(_) => ErrorHandling::convert(FxaError::OriginMismatch),
239 Error::MalformedUrl { .. } => {
242 ErrorHandling::convert(FxaError::Other(self.to_string())).log_warning()
243 }
244 _ => ErrorHandling::convert(FxaError::Other(self.to_string()))
245 .report_error("fxa-client-other-error"),
246 }
247 }
248}