systemprompt_cloud/
error.rs1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum CloudError {
5 #[error("Authentication required.\n\nRun: systemprompt cloud login")]
6 NotAuthenticated,
7
8 #[error("Token expired.\n\nRun: systemprompt cloud login")]
9 TokenExpired,
10
11 #[error("No tenant configured.\n\nRun: systemprompt cloud setup")]
12 TenantNotConfigured,
13
14 #[error("No app configured.\n\nRun: systemprompt cloud setup")]
15 AppNotConfigured,
16
17 #[error(
18 "Profile required: {message}\n\nSet SYSTEMPROMPT_PROFILE or run 'systemprompt cloud \
19 config'"
20 )]
21 ProfileRequired { message: String },
22
23 #[error("Missing profile field: {field}\n\nAdd to your profile:\n{example}")]
24 MissingProfileField { field: String, example: String },
25
26 #[error("JWT decode error")]
27 JwtDecode,
28
29 #[error("Credentials file corrupted.\n\nRun: systemprompt cloud login")]
30 CredentialsCorrupted {
31 #[source]
32 source: serde_json::Error,
33 },
34
35 #[error("Tenants not synced.\n\nRun: systemprompt cloud login")]
36 TenantsNotSynced,
37
38 #[error("Tenants store corrupted.\n\nRun: systemprompt cloud login")]
39 TenantsStoreCorrupted {
40 #[source]
41 source: serde_json::Error,
42 },
43
44 #[error("Tenants store invalid: {message}")]
45 TenantsStoreInvalid { message: String },
46
47 #[error("Tenant '{tenant_id}' not found.\n\nRun: systemprompt cloud config")]
48 TenantNotFound { tenant_id: String },
49
50 #[error("API error: {message}")]
51 ApiError { message: String },
52
53 #[error(transparent)]
54 Network(#[from] reqwest::Error),
55
56 #[error(transparent)]
57 Io(#[from] std::io::Error),
58}
59
60pub type CloudResult<T> = Result<T, CloudError>;
61
62impl CloudError {
63 pub const fn user_message(&self) -> &'static str {
64 match self {
65 Self::NotAuthenticated => "Not logged in to systemprompt.io Cloud",
66 Self::TokenExpired => "Your session has expired",
67 Self::TenantNotConfigured => "No project linked to this environment",
68 Self::AppNotConfigured => "No deployment target configured",
69 Self::ProfileRequired { .. } => "Profile configuration required",
70 Self::MissingProfileField { .. } => "Missing required profile field",
71 Self::JwtDecode => "Failed to decode authentication token",
72 Self::CredentialsCorrupted { .. } => "Credentials file is corrupted",
73 Self::TenantsNotSynced => "Tenants not synced locally",
74 Self::TenantsStoreCorrupted { .. } => "Tenants store is corrupted",
75 Self::TenantsStoreInvalid { .. } => "Tenants store is invalid",
76 Self::TenantNotFound { .. } => "Tenant not found",
77 Self::ApiError { .. } => "API request failed",
78 Self::Network(_) => "Network error communicating with cloud",
79 Self::Io(_) => "File system error",
80 }
81 }
82
83 pub const fn recovery_hint(&self) -> &'static str {
84 match self {
85 Self::NotAuthenticated | Self::TokenExpired => {
86 "Run 'systemprompt cloud login' to authenticate"
87 },
88 Self::TenantNotConfigured | Self::AppNotConfigured => {
89 "Run 'systemprompt cloud setup' to configure your project"
90 },
91 Self::ProfileRequired { .. } => {
92 "Set SYSTEMPROMPT_PROFILE or run 'systemprompt cloud config'"
93 },
94 Self::MissingProfileField { .. } => "Add the missing field to your profile YAML",
95 Self::JwtDecode | Self::CredentialsCorrupted { .. } => {
96 "Run 'systemprompt cloud login' to re-authenticate"
97 },
98 Self::TenantsNotSynced
99 | Self::TenantsStoreCorrupted { .. }
100 | Self::TenantsStoreInvalid { .. } => "Run 'systemprompt cloud login' to sync tenants",
101 Self::TenantNotFound { .. } => {
102 "Run 'systemprompt cloud config' to select a valid tenant"
103 },
104 Self::ApiError { .. } => "Check the error message and try again",
105 Self::Network(_) => "Check your internet connection and try again",
106 Self::Io(_) => "Check file permissions and disk space",
107 }
108 }
109
110 pub const fn requires_login(&self) -> bool {
111 matches!(
112 self,
113 Self::NotAuthenticated | Self::TokenExpired | Self::CredentialsCorrupted { .. }
114 )
115 }
116
117 pub const fn requires_setup(&self) -> bool {
118 matches!(self, Self::TenantNotConfigured | Self::AppNotConfigured)
119 }
120}