manta_shared/common/error.rs
1//! Structured error type returned by `manta-shared`'s pure helpers.
2//!
3//! Replaces the previous use of `manta_backend_dispatcher::error::Error`
4//! in audit / jwt / kafka / config / sat-file / network-probe helpers,
5//! so that this crate (and therefore `manta-cli`) no longer needs to
6//! reach into backend-dispatcher types for its error surface.
7//!
8//! Server-side code keeps returning `manta_backend_dispatcher::error::Error`
9//! and uses `?` to convert `MantaError` at the call site via the
10//! `From<MantaError> for BackendError` impl in
11//! `crates/manta-server/src/wire_conv.rs`.
12
13use thiserror::Error;
14
15/// Errors returned by `manta-shared`'s pure helpers.
16///
17/// Most helpers return `Result<T, MantaError>`. The server-side code
18/// converts these to its richer `BackendError` via
19/// `crates/manta-server/src/wire_conv.rs::to_backend`, which then
20/// maps to HTTP status codes.
21///
22/// # Examples
23///
24/// Pattern-match a NotFound to log a custom message before propagating:
25///
26/// ```
27/// use manta_shared::common::error::MantaError;
28///
29/// fn lookup_thing() -> Result<(), MantaError> {
30/// Err(MantaError::NotFound("thing 42".into()))
31/// }
32///
33/// match lookup_thing() {
34/// Err(MantaError::NotFound(detail)) => {
35/// // Maps to HTTP 404 server-side.
36/// assert_eq!(detail, "thing 42");
37/// }
38/// _ => unreachable!(),
39/// }
40/// ```
41#[derive(Error, Debug)]
42pub enum MantaError {
43 /// Filesystem I/O failure (config-file read, audit-log write, etc.).
44 #[error("IO error: {0}")]
45 IoError(#[from] std::io::Error),
46 /// `config` crate failure: bad TOML, env-var parse, or schema
47 /// mismatch on `cli.toml` / `server.toml`.
48 #[error("Config error: {0}")]
49 ConfigError(#[from] config::ConfigError),
50 /// `toml_edit` parse / serialize failure when editing a config
51 /// file in place (e.g. `manta config set`).
52 #[error("TOML edit error: {0}")]
53 TomlEditError(#[from] toml_edit::TomlError),
54 /// JSON serialize / deserialize failure (most often during JWT
55 /// claim extraction or audit payload construction).
56 #[error("Serde error: {0}")]
57 SerdeError(#[from] serde_json::Error),
58 /// `reqwest` failure on outbound HTTP (DNS, TLS handshake, body
59 /// stream, etc.).
60 #[error("Network error: {0}")]
61 NetError(#[from] reqwest::Error),
62 /// YAML parse / serialize failure (SAT-file rendering).
63 #[error("YAML error: {0}")]
64 YamlError(#[from] serde_yaml::Error),
65
66 /// Resource lookup failed (config file missing, group not in
67 /// backend, etc.). Maps to HTTP 404 server-side.
68 #[error("Not found: {0}")]
69 NotFound(String),
70 /// A required field is absent (e.g. JWT lacks `preferred_username`,
71 /// node config lacks `boot_image_id`).
72 #[error("Missing field: {0}")]
73 MissingField(String),
74 /// JWT was structurally invalid (wrong number of dots, undecodable
75 /// claims, non-UTF-8 payload). Maps to HTTP 401.
76 #[error("JWT malformed: {0}")]
77 JwtMalformed(String),
78 /// Kafka producer construction or delivery failed.
79 #[error("Kafka error: {0}")]
80 KafkaError(String),
81 /// User-supplied pattern (hardware pattern, hostlist expression,
82 /// glob) didn't parse. Maps to HTTP 400.
83 #[error("Invalid pattern: {0}")]
84 InvalidPattern(String),
85 /// Jinja2 / minijinja render failed during SAT-file processing.
86 #[error("Template render error: {0}")]
87 TemplateError(String),
88
89 /// Catch-all for messages that don't fit any structured variant.
90 /// Server-side this maps to HTTP 500 — prefer a typed variant when
91 /// adding new failure modes.
92 #[error("{0}")]
93 Other(String),
94}