syncable_cli/platform/api/
error.rs1use thiserror::Error;
6
7#[derive(Debug, Error)]
9pub enum PlatformApiError {
10 #[error("HTTP request failed: {0}")]
12 HttpError(#[from] reqwest::Error),
13
14 #[error("API error ({status}): {message}")]
16 ApiError {
17 status: u16,
19 message: String,
21 },
22
23 #[error("Failed to parse response: {0}")]
25 ParseError(String),
26
27 #[error("Not authenticated - run `sync-ctl auth login` first")]
29 Unauthorized,
30
31 #[error("Not found: {0}")]
33 NotFound(String),
34
35 #[error("Permission denied: {0}")]
37 PermissionDenied(String),
38
39 #[error("Rate limit exceeded - please try again later")]
41 RateLimited,
42
43 #[error("Server error ({status}): {message}")]
45 ServerError {
46 status: u16,
48 message: String,
50 },
51
52 #[error("Could not connect to Syncable API - check your internet connection")]
54 ConnectionFailed,
55}
56
57impl PlatformApiError {
58 pub fn suggestion(&self) -> Option<&'static str> {
62 match self {
63 Self::Unauthorized => Some("Run `sync-ctl auth login` to authenticate"),
64 Self::RateLimited => Some("Wait a moment and try again"),
65 Self::HttpError(_) => Some("Check your internet connection"),
66 Self::ServerError { .. } => {
67 Some("The server is experiencing issues. Try again later")
68 }
69 Self::PermissionDenied(_) => {
70 Some("Check your project permissions in the Syncable dashboard")
71 }
72 Self::NotFound(_) => Some("Verify the resource ID is correct"),
73 Self::ParseError(_) => Some("This may be a bug - please report it"),
74 Self::ApiError { status, .. } if *status >= 400 && *status < 500 => {
75 Some("Check the request parameters")
76 }
77 Self::ConnectionFailed => {
78 Some("Check your internet connection and try again")
79 }
80 _ => None,
81 }
82 }
83
84 pub fn with_suggestion(&self) -> String {
88 match self.suggestion() {
89 Some(suggestion) => format!("{}\n → {}", self, suggestion),
90 None => self.to_string(),
91 }
92 }
93}
94
95pub type Result<T> = std::result::Result<T, PlatformApiError>;