Skip to main content

bwx/
error.rs

1#[derive(thiserror::Error, Debug)]
2pub enum Error {
3    #[error("email address not set")]
4    ConfigMissingEmail,
5
6    #[error("failed to create block mode decryptor")]
7    CreateBlockMode { source: aes::cipher::InvalidLength },
8
9    #[error("failed to create block mode decryptor")]
10    CreateHmac { source: aes::cipher::InvalidLength },
11
12    #[error("failed to create directory at {}", .file.display())]
13    CreateDirectory {
14        source: std::io::Error,
15        file: std::path::PathBuf,
16    },
17
18    #[error("failed to create reqwest client")]
19    CreateReqwestClient { source: reqwest::Error },
20
21    #[error("failed to create sso callback server: {err}")]
22    CreateSSOCallbackServer { err: std::io::Error },
23
24    #[error("failed to decrypt: {msg}")]
25    Decrypt { msg: String },
26
27    #[error("failed to find free port in {range}")]
28    FailedToFindFreePort { range: String },
29
30    #[error("failed to parse pinentry output ({out:?})")]
31    FailedToParsePinentry { out: String },
32
33    #[error("failed to process sso callback ({msg})")]
34    FailedToProcessSSOCallback { msg: String },
35
36    #[error("failed to open web browser: {err}")]
37    FailedToOpenWebBrowser { err: std::io::Error },
38
39    #[error("failed to read from stdin: {err}")]
40    FailedToReadFromStdin { err: std::io::Error },
41
42    #[error(
43        "failed to run editor {}: {err}",
44        .editor.to_string_lossy(),
45    )]
46    FailedToFindEditor {
47        editor: std::path::PathBuf,
48        err: std::io::Error,
49    },
50
51    #[error(
52        "failed to run editor {} {}: {res:?}",
53        .editor.to_string_lossy(),
54        .args.iter().map(|s| s.to_string_lossy()).collect::<Vec<_>>().join(" ")
55    )]
56    FailedToRunEditor {
57        editor: std::path::PathBuf,
58        args: Vec<std::ffi::OsString>,
59        res: std::process::ExitStatus,
60    },
61
62    #[error("failed to expand with hkdf")]
63    HkdfExpand,
64
65    #[error("incorrect api key")]
66    IncorrectApiKey,
67
68    #[error("{message}")]
69    IncorrectPassword { message: String },
70
71    #[error("invalid base64")]
72    InvalidBase64 { source: base64::DecodeError },
73
74    #[error("invalid cipherstring: {reason}")]
75    InvalidCipherString { reason: String },
76
77    #[error(
78        "invalid value for ${var}: {}",
79        .editor.to_string_lossy()
80    )]
81    InvalidEditor {
82        var: String,
83        editor: std::ffi::OsString,
84    },
85
86    #[error("invalid mac")]
87    InvalidMac,
88
89    #[error("invalid two factor provider type: {ty}")]
90    InvalidTwoFactorProvider { ty: String },
91
92    #[error("failed to parse JSON")]
93    Json { source: serde_json::Error },
94
95    #[error("failed to load config from {}", .file.display())]
96    LoadConfig {
97        source: std::io::Error,
98        file: std::path::PathBuf,
99    },
100
101    #[error("failed to load config from {}", .file.display())]
102    LoadConfigAsync {
103        source: tokio::io::Error,
104        file: std::path::PathBuf,
105    },
106
107    #[error("failed to load config from {}", .file.display())]
108    LoadConfigJson {
109        source: serde_json::Error,
110        file: std::path::PathBuf,
111    },
112
113    #[error("failed to load db from {}", .file.display())]
114    LoadDb {
115        source: std::io::Error,
116        file: std::path::PathBuf,
117    },
118
119    #[error("failed to load db from {}", .file.display())]
120    LoadDbAsync {
121        source: tokio::io::Error,
122        file: std::path::PathBuf,
123    },
124
125    #[error("failed to load db from {}", .file.display())]
126    LoadDbJson {
127        source: serde_json::Error,
128        file: std::path::PathBuf,
129    },
130
131    #[error("failed to load device id from {}", .file.display())]
132    LoadDeviceId {
133        source: tokio::io::Error,
134        file: std::path::PathBuf,
135    },
136
137    #[error("failed to load client cert from {}", .file.display())]
138    LoadClientCert {
139        source: tokio::io::Error,
140        file: std::path::PathBuf,
141    },
142
143    #[error("invalid padding")]
144    Padding,
145
146    #[error("failed to parse match type {s}")]
147    ParseMatchType { s: String },
148
149    #[error("pbkdf2 requires at least 1 iteration (got 0)")]
150    Pbkdf2ZeroIterations,
151
152    #[error("failed to run pbkdf2")]
153    Pbkdf2,
154
155    #[error("failed to run argon2")]
156    Argon2,
157
158    #[error("pinentry cancelled")]
159    PinentryCancelled,
160
161    #[error("native password prompt unavailable on this platform")]
162    NativePromptUnsupported,
163
164    #[error("native password prompt failed at {stage}: code {code}")]
165    NativePromptFailed { code: i32, stage: &'static str },
166
167    #[error("pinentry error: {error}")]
168    PinentryErrorMessage { error: String },
169
170    #[error("error reading pinentry output")]
171    PinentryReadOutput { source: tokio::io::Error },
172
173    #[error("error waiting for pinentry to exit")]
174    PinentryWait { source: tokio::io::Error },
175
176    #[error("This device has not yet been registered with the Bitwarden server. Run `bwx register` first, and then try again.")]
177    RegistrationRequired,
178
179    #[error("failed to remove db at {}", .file.display())]
180    RemoveDb {
181        source: std::io::Error,
182        file: std::path::PathBuf,
183    },
184
185    #[error("api request returned error: {status}")]
186    RequestFailed { status: u16 },
187
188    #[error("api request unauthorized")]
189    RequestUnauthorized,
190
191    #[error("error making api request")]
192    Reqwest { source: reqwest::Error },
193
194    #[error("failed to decrypt")]
195    Rsa { source: rsa::errors::Error },
196
197    #[error("failed to decrypt")]
198    RsaPkcs8 { source: rsa::pkcs8::Error },
199
200    #[error("failed to save config to {}", .file.display())]
201    SaveConfig {
202        source: std::io::Error,
203        file: std::path::PathBuf,
204    },
205
206    #[error("failed to save config to {}", .file.display())]
207    SaveConfigJson {
208        source: serde_json::Error,
209        file: std::path::PathBuf,
210    },
211
212    #[error("failed to save db to {}", .file.display())]
213    SaveDb {
214        source: std::io::Error,
215        file: std::path::PathBuf,
216    },
217
218    #[error("failed to save db to {}", .file.display())]
219    SaveDbAsync {
220        source: tokio::io::Error,
221        file: std::path::PathBuf,
222    },
223
224    #[error("failed to save db to {}", .file.display())]
225    SaveDbJson {
226        source: serde_json::Error,
227        file: std::path::PathBuf,
228    },
229
230    #[error("error spawning pinentry")]
231    Spawn { source: tokio::io::Error },
232
233    #[error("cipherstring type {ty} too old\n\nPlease rotate your account encryption key (https://bitwarden.com/help/article/account-encryption-key/) and try again.")]
234    TooOldCipherStringType { ty: String },
235
236    #[error("two factor required")]
237    TwoFactorRequired {
238        providers: Vec<crate::api::TwoFactorProviderType>,
239        sso_email_2fa_session_token: Option<String>,
240    },
241
242    #[error("unimplemented cipherstring type: {ty}")]
243    UnimplementedCipherStringType { ty: String },
244
245    #[error("error writing to pinentry stdin")]
246    WriteStdin { source: tokio::io::Error },
247
248    #[error("invalid kdf type: {ty}")]
249    InvalidKdfType { ty: String },
250
251    #[error("{msg}")]
252    Totp { msg: String },
253}
254
255pub type Result<T> = std::result::Result<T, Error>;