1use thiserror::Error;
4
5use super::peer_types::Address;
6use crate::{auth::Permission, entry::ID};
7
8#[derive(Debug, Error)]
10#[non_exhaustive]
11pub enum SyncError {
12 #[error("No transport enabled. Call enable_http_transport() first")]
14 NoTransportEnabled,
15
16 #[error("Server already running on {address}")]
18 ServerAlreadyRunning { address: String },
19
20 #[error("Server not running")]
22 ServerNotRunning,
23
24 #[error("Unexpected response type: expected {expected}, got {actual}")]
26 UnexpectedResponse {
27 expected: &'static str,
28 actual: String,
29 },
30
31 #[error("Network error: {0}")]
33 Network(String),
34
35 #[error("Failed to send command to background sync: {0}")]
37 CommandSendError(String),
38
39 #[error("Failed to initialize transport: {0}")]
41 TransportInit(String),
42
43 #[error("Failed to create async runtime: {0}")]
45 RuntimeCreation(String),
46
47 #[error("Failed to bind server to {address}: {reason}")]
49 ServerBind { address: String, reason: String },
50
51 #[error("Failed to connect to {address}: {reason}")]
53 ConnectionFailed { address: String, reason: String },
54
55 #[error("Device key '{key_name}' not found in backend storage")]
57 DeviceKeyNotFound { key_name: String },
58
59 #[error("Transport type '{transport_type}' not supported")]
61 UnsupportedTransport { transport_type: String },
62
63 #[error("Invalid address: {0}")]
65 InvalidAddress(String),
66
67 #[error("Peer not found: {0}")]
69 PeerNotFound(String),
70
71 #[error("Peer already exists: {0}")]
73 PeerAlreadyExists(String),
74
75 #[error("Serialization error: {0}")]
77 SerializationError(String),
78
79 #[error("Protocol version mismatch: expected {expected}, received {received}")]
81 ProtocolMismatch { expected: u32, received: u32 },
82
83 #[error("Handshake failed: {0}")]
85 HandshakeFailed(String),
86
87 #[error("Entry not found: {0}")]
89 EntryNotFound(ID),
90
91 #[error("Invalid entry: {0}")]
93 InvalidEntry(String),
94
95 #[error("Sync protocol error: {0}")]
97 SyncProtocolError(String),
98
99 #[error("Backend error: {0}")]
101 BackendError(String),
102
103 #[error("Bootstrap request not found: {0}")]
105 RequestNotFound(String),
106
107 #[error("Bootstrap request already exists: {0}")]
109 RequestAlreadyExists(String),
110
111 #[error(
113 "Invalid request state for '{request_id}': expected {expected_status}, found {current_status}"
114 )]
115 InvalidRequestState {
116 request_id: String,
117 current_status: String,
118 expected_status: String,
119 },
120
121 #[error("Invalid data: {0}")]
123 InvalidData(String),
124
125 #[error(
127 "Insufficient permission for request '{request_id}': required {required_permission}, but key has {actual_permission:?}"
128 )]
129 InsufficientPermission {
130 request_id: String,
131 required_permission: String,
132 actual_permission: Permission,
133 },
134
135 #[error("Invalid public key: {reason}")]
137 InvalidPublicKey { reason: String },
138
139 #[error("Invalid key name: {reason}")]
141 InvalidKeyName { reason: String },
142
143 #[error("Instance has been dropped")]
145 InstanceDropped,
146
147 #[error("Bootstrap request pending approval (request_id: {request_id}): {message}")]
149 BootstrapPending { request_id: String, message: String },
150
151 #[error("Transport config type mismatch for '{name}': expected '{expected}', found '{found}'")]
153 TransportTypeMismatch {
154 name: String,
155 expected: String,
156 found: String,
157 },
158
159 #[error("Transport not found: {name}")]
161 TransportNotFound { name: String },
162
163 #[error("No transport can handle address: {address:?}")]
165 NoTransportForAddress { address: Address },
166
167 #[error("Multiple transport errors: {}", errors.join(", "))]
169 MultipleTransportErrors { errors: Vec<String> },
170}
171
172impl SyncError {
173 pub fn is_configuration_error(&self) -> bool {
175 matches!(self, SyncError::NoTransportEnabled)
176 }
177
178 pub fn is_server_error(&self) -> bool {
180 matches!(
181 self,
182 SyncError::ServerAlreadyRunning { .. }
183 | SyncError::ServerNotRunning
184 | SyncError::ServerBind { .. }
185 )
186 }
187
188 pub fn is_network_error(&self) -> bool {
190 matches!(
191 self,
192 SyncError::Network(_) | SyncError::ConnectionFailed { .. }
193 )
194 }
195
196 pub fn is_protocol_error(&self) -> bool {
198 matches!(self, SyncError::UnexpectedResponse { .. })
199 }
200
201 pub fn is_not_found(&self) -> bool {
203 matches!(
204 self,
205 SyncError::PeerNotFound(_) | SyncError::EntryNotFound(_)
206 )
207 }
208
209 pub fn is_validation_error(&self) -> bool {
211 matches!(
212 self,
213 SyncError::InvalidEntry(_)
214 | SyncError::InvalidPublicKey { .. }
215 | SyncError::InvalidKeyName { .. }
216 )
217 }
218
219 pub fn is_backend_error(&self) -> bool {
221 matches!(self, SyncError::BackendError(_))
222 }
223}