Skip to main content

syncable_cli/platform/api/
error.rs

1//! Error types for the Platform API client
2//!
3//! Provides structured error types for all API operations.
4
5use thiserror::Error;
6
7/// Errors that can occur when interacting with the Syncable Platform API
8#[derive(Debug, Error)]
9pub enum PlatformApiError {
10    /// HTTP request failed (network error, timeout, etc.)
11    #[error("HTTP request failed: {0}")]
12    HttpError(#[from] reqwest::Error),
13
14    /// API returned an error response
15    #[error("API error ({status}): {message}")]
16    ApiError {
17        /// HTTP status code
18        status: u16,
19        /// Error message from the API
20        message: String,
21    },
22
23    /// Failed to parse the API response
24    #[error("Failed to parse response: {0}")]
25    ParseError(String),
26
27    /// User is not authenticated - needs to run `sync-ctl auth login`
28    #[error("Not authenticated - run `sync-ctl auth login` first")]
29    Unauthorized,
30
31    /// Requested resource was not found
32    #[error("Not found: {0}")]
33    NotFound(String),
34
35    /// User does not have permission for the requested operation
36    #[error("Permission denied: {0}")]
37    PermissionDenied(String),
38
39    /// Rate limit exceeded
40    #[error("Rate limit exceeded - please try again later")]
41    RateLimited,
42
43    /// Server error
44    #[error("Server error ({status}): {message}")]
45    ServerError {
46        /// HTTP status code (5xx)
47        status: u16,
48        /// Error message
49        message: String,
50    },
51
52    /// Could not connect to the Syncable API
53    #[error("Could not connect to Syncable API - check your internet connection")]
54    ConnectionFailed,
55}
56
57impl PlatformApiError {
58    /// Get a user-friendly suggestion for resolving this error
59    ///
60    /// Returns actionable advice that helps users fix the issue.
61    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 { .. } => Some("The server is experiencing issues. Try again later"),
67            Self::PermissionDenied(_) => {
68                Some("Check your project permissions in the Syncable dashboard")
69            }
70            Self::NotFound(_) => Some("Verify the resource ID is correct"),
71            Self::ParseError(_) => Some("This may be a bug - please report it"),
72            Self::ApiError { status, .. } if *status >= 400 && *status < 500 => {
73                Some("Check the request parameters")
74            }
75            Self::ConnectionFailed => Some("Check your internet connection and try again"),
76            _ => None,
77        }
78    }
79
80    /// Format the error with suggestion if available
81    ///
82    /// Returns the error message followed by a suggestion on how to resolve it.
83    pub fn with_suggestion(&self) -> String {
84        match self.suggestion() {
85            Some(suggestion) => format!("{}\n  → {}", self, suggestion),
86            None => self.to_string(),
87        }
88    }
89}
90
91/// Result type alias for Platform API operations
92pub type Result<T> = std::result::Result<T, PlatformApiError>;