zammad_api/error.rs
1use serde_json::Value;
2use thiserror::Error;
3
4/// Convenience alias for `Result<T, zammad_api::Error>`.
5pub type Result<T, E = Error> = std::result::Result<T, E>;
6
7/// Every error this crate can produce.
8#[derive(Debug, Error)]
9pub enum Error {
10 /// The base URL passed to the builder could not be parsed.
11 #[error("invalid base URL: {0}")]
12 InvalidUrl(#[from] url::ParseError),
13
14 /// Transport-level failure (DNS, TLS, timeout, broken pipe, ...).
15 #[error("HTTP error: {0}")]
16 Http(#[from] reqwest::Error),
17
18 /// The server responded with a non-success status code.
19 #[error("Zammad API error ({status}): {message}")]
20 Api {
21 /// HTTP status code returned by Zammad.
22 status: u16,
23 /// Decoded `error` / `error_human` field, or the raw response body.
24 message: String,
25 },
26
27 /// The requested resource does not exist (HTTP 404).
28 #[error("resource not found")]
29 NotFound,
30
31 /// A write was issued but the server did not persist the new value.
32 ///
33 /// Zammad silently returns `200 OK` with the unchanged entity when you
34 /// PUT to a custom field that is not declared on the object - this
35 /// variant turns that into a loud, actionable failure. The `actual`
36 /// value is whatever the server echoed back for `field` (often `null`
37 /// or the previous value).
38 #[error(
39 "write verification failed: field `{field}` was not persisted (got {actual:?}); \
40 ensure the custom attribute exists and any pending migrations have been executed"
41 )]
42 WriteVerificationFailed {
43 /// Name of the field that failed to persist.
44 field: String,
45 /// Value the server returned after the write.
46 actual: Option<Value>,
47 },
48
49 /// The server returned an unexpected payload.
50 #[error("decode error: {0}")]
51 Decode(#[from] serde_json::Error),
52
53 /// The configuration passed to [`crate::ClientBuilder`] is invalid.
54 #[error("invalid configuration: {0}")]
55 Config(String),
56}