rtb_error/lib.rs
1//! Error types and the diagnostic-report pipeline.
2//!
3//! The framework follows the `thiserror` + `miette` pattern:
4//!
5//! * Library-level crates define typed errors with
6//! `#[derive(thiserror::Error, miette::Diagnostic)]`.
7//! * At the process boundary (`fn main() -> miette::Result<()>`), errors
8//! are rendered by a `miette` hook installed via [`hook`].
9//! * There is **no** `ErrorHandler` trait or `.check()` funnel — errors
10//! are values, propagated with `?`, and reported once at the edge.
11//!
12//! See `docs/development/specs/2026-04-22-rtb-error-v0.1.md` for the
13//! authoritative contract.
14
15#![forbid(unsafe_code)]
16
17pub use miette::{Diagnostic, Report};
18
19pub mod exit_code;
20pub use exit_code::{exit_code_of, ExitCoded, WithExitCode};
21
22use thiserror::Error;
23
24/// Canonical framework result alias.
25pub type Result<T, E = Error> = std::result::Result<T, E>;
26
27/// Umbrella error enum for the framework.
28///
29/// Downstream crates should define their own `#[derive(Error, Diagnostic)]`
30/// enums and convert at the boundary. This enum captures only the errors
31/// raised by the application scaffolding itself, plus the [`Error::Other`]
32/// escape hatch for downstream typed diagnostics.
33#[derive(Debug, Error, Diagnostic)]
34#[non_exhaustive]
35pub enum Error {
36 /// Configuration source rejected the value.
37 #[error("configuration error: {0}")]
38 #[diagnostic(code(rtb::config))]
39 Config(String),
40
41 /// Filesystem or network I/O.
42 #[error("I/O error: {0}")]
43 #[diagnostic(code(rtb::io))]
44 Io(#[from] std::io::Error),
45
46 /// No registered command matches the user-supplied name.
47 #[error("command not found: {0}")]
48 #[diagnostic(code(rtb::command_not_found), help("run `--help` to list available commands"))]
49 CommandNotFound(String),
50
51 /// A built-in command was requested but its Cargo feature is off.
52 #[error("feature `{0}` is not compiled in")]
53 #[diagnostic(
54 code(rtb::feature_disabled),
55 help("rebuild with the appropriate Cargo feature enabled")
56 )]
57 FeatureDisabled(&'static str),
58
59 /// A downstream crate's typed diagnostic, kept live for rendering.
60 #[error("{0}")]
61 #[diagnostic(transparent)]
62 Other(#[from] Box<dyn Diagnostic + Send + Sync + 'static>),
63}
64
65pub mod hook;