oauth_device_flows/
error.rs1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, DeviceFlowError>;
7
8#[derive(Error, Debug)]
10pub enum DeviceFlowError {
11 #[error("Network error: {0}")]
13 Network(#[from] reqwest::Error),
14
15 #[error("JSON parsing error: {0}")]
17 Json(#[from] serde_json::Error),
18
19 #[error("URL parsing error: {0}")]
21 Url(#[from] url::ParseError),
22
23 #[error("OAuth error: {error} - {error_description}")]
25 OAuth {
26 error: String,
27 error_description: String,
28 },
29
30 #[error("Authorization denied")]
32 AuthorizationDenied,
33
34 #[error("Device code expired")]
36 ExpiredToken,
37
38 #[error("Polling too frequently, slow down")]
40 SlowDown,
41
42 #[error("Authorization pending")]
44 AuthorizationPending,
45
46 #[error("Invalid device code")]
48 InvalidCode,
49
50 #[error("Invalid client configuration: {0}")]
52 InvalidClient(String),
53
54 #[error("Token expired and refresh failed")]
56 TokenExpired,
57
58 #[error("Unsupported provider: {0}")]
60 UnsupportedProvider(String),
61
62 #[error("Maximum polling attempts ({0}) exceeded")]
64 MaxAttemptsExceeded(u32),
65
66 #[error("Invalid scope: {0}")]
68 InvalidScope(String),
69
70 #[cfg(feature = "qr-codes")]
72 #[error("QR code generation error: {0}")]
73 QrCode(#[from] qrcode::types::QrError),
74
75 #[error("Unexpected error: {0}")]
77 Other(String),
78}
79
80impl DeviceFlowError {
81 pub fn oauth_error(error: impl Into<String>, description: impl Into<String>) -> Self {
83 Self::OAuth {
84 error: error.into(),
85 error_description: description.into(),
86 }
87 }
88
89 pub fn invalid_client(message: impl Into<String>) -> Self {
91 Self::InvalidClient(message.into())
92 }
93
94 pub fn other(message: impl Into<String>) -> Self {
96 Self::Other(message.into())
97 }
98
99 pub fn is_retryable(&self) -> bool {
101 matches!(
102 self,
103 Self::Network(_) | Self::AuthorizationPending | Self::SlowDown
104 )
105 }
106
107 pub fn is_slow_down(&self) -> bool {
109 matches!(self, Self::SlowDown)
110 }
111
112 pub fn is_pending(&self) -> bool {
114 matches!(self, Self::AuthorizationPending)
115 }
116}