rtb_config/error.rs
1//! Typed errors for the config subsystem.
2
3use std::path::PathBuf;
4
5use miette::Diagnostic;
6use thiserror::Error;
7
8/// Failures surfaced by [`crate::Config`] construction and reload.
9///
10/// Every variant carries a `miette::Diagnostic` code under the
11/// `rtb::config::*` namespace so users get consistent error surfaces
12/// across the framework.
13#[derive(Debug, Error, Diagnostic)]
14#[non_exhaustive]
15pub enum ConfigError {
16 /// Figment refused the merged source set — parse failure, missing
17 /// required field, or serde type mismatch.
18 #[error("configuration error: {0}")]
19 #[diagnostic(
20 code(rtb::config::parse),
21 help("check your config file and environment variables against the schema")
22 )]
23 Parse(String),
24
25 /// User config file was referenced but could not be read.
26 #[error("could not read config file {path}: {source}")]
27 #[diagnostic(code(rtb::config::io))]
28 Io {
29 /// The path that could not be read.
30 path: PathBuf,
31 /// The underlying I/O error.
32 #[source]
33 source: std::io::Error,
34 },
35
36 /// File watcher failed — no user-file paths registered, OS handle
37 /// limit, or an I/O error from the underlying `notify` backend.
38 /// Only constructable when the `hot-reload` feature is enabled,
39 /// but the variant is unconditionally present so downstream
40 /// `match` arms don't need cfg-gating.
41 #[error("config watcher error: {0}")]
42 #[diagnostic(code(rtb::config::watch))]
43 Watch(String),
44
45 /// Serialisation or filesystem failure when writing the merged
46 /// value back to disk via `Config::write`. Constructable only
47 /// when the `mutable` feature is enabled, but the variant is
48 /// unconditional so consumers' `match` arms stay cfg-clean.
49 /// (`Config::write` is cfg-gated; the intra-doc link would
50 /// only resolve under `--features mutable` doc builds.)
51 #[error("config write error: {0}")]
52 #[diagnostic(code(rtb::config::write))]
53 Write(String),
54
55 /// Schema-validation failure during a `Config::write`
56 /// candidate-validation step, or any other consumer that
57 /// validates against `Config::schema`. Cfg-gated; see the
58 /// `Write` variant's note about doc-link resolution.
59 #[error("config schema violation: {0}")]
60 #[diagnostic(code(rtb::config::schema))]
61 Schema(String),
62}
63
64impl From<figment::Error> for ConfigError {
65 fn from(value: figment::Error) -> Self {
66 Self::Parse(value.to_string())
67 }
68}