1use thiserror::Error;
4
5#[derive(Debug, Error)]
6pub enum ClientError {
7 #[error(
8 "pidge has not been provisioned yet. The maintainer needs to run scripts/register-pidge-app.sh and update APP_CLIENT_ID."
9 )]
10 NotProvisioned,
11
12 #[error("OS keychain unavailable: {0}")]
13 Keychain(#[from] keyring::Error),
14
15 #[error("could not determine the user config directory")]
16 NoConfigDir,
17
18 #[error("io: {0}")]
19 Io(#[from] std::io::Error),
20
21 #[error("device code flow: authorization pending exceeded poll deadline")]
22 DeviceCodeTimeout,
23
24 #[error("device code flow: user denied consent")]
25 DeviceCodeAccessDenied,
26
27 #[error("device code flow: {kind}{}", description.as_ref().map(|d| format!(": {d}")).unwrap_or_default())]
28 DeviceCodeOther {
29 kind: String,
30 description: Option<String>,
31 },
32
33 #[error("session expired for {email}. Run `pidge account add` to re-add this account.")]
34 SessionExpired { email: String },
35
36 #[error(
42 "session expired for the hosted pidge server. Run `pidge mcp connect {server}` to sign in again."
43 )]
44 McpSessionExpired { server: String },
45
46 #[error("http: {0}")]
47 Http(#[from] reqwest::Error),
48
49 #[error("json: {0}")]
50 Json(#[from] serde_json::Error),
51
52 #[error("Microsoft Graph: {status} {message}")]
53 Graph { status: u16, message: String },
54
55 #[error(
56 "Microsoft Graph is throttling requests{}. Try again later.",
57 retry_after.map(|s| format!(" (retry after {s}s)")).unwrap_or_default()
58 )]
59 Throttled { retry_after: Option<u64> },
60
61 #[error("the delta cursor has expired; re-bootstrap without --cursor")]
62 DeltaExpired,
63
64 #[error("core: {0}")]
65 Core(#[from] pidge_core::CoreError),
66
67 #[error("unsubscribe request rejected")]
71 UnsubscribeRejected,
72
73 #[error("token response missing access_token")]
74 MissingAccessToken,
75}