Skip to main content

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 [spec 0006] on the rust-tool-base wiki for the authoritative
13//! contract.
14//!
15//! [spec 0006]: https://gitlab.com/phpboyscout/rust-tool-base/-/wikis/specs/0006-rtb-error-v0.1
16
17#![forbid(unsafe_code)]
18
19pub use miette::{Diagnostic, Report};
20
21pub mod exit_code;
22pub use exit_code::{exit_code_of, ExitCoded, WithExitCode};
23
24use thiserror::Error;
25
26/// Canonical framework result alias.
27pub type Result<T, E = Error> = std::result::Result<T, E>;
28
29/// Umbrella error enum for the framework.
30///
31/// Downstream crates should define their own `#[derive(Error, Diagnostic)]`
32/// enums and convert at the boundary. This enum captures only the errors
33/// raised by the application scaffolding itself, plus the [`Error::Other`]
34/// escape hatch for downstream typed diagnostics.
35#[derive(Debug, Error, Diagnostic)]
36#[non_exhaustive]
37pub enum Error {
38    /// Configuration source rejected the value.
39    #[error("configuration error: {0}")]
40    #[diagnostic(code(rtb::config))]
41    Config(String),
42
43    /// Filesystem or network I/O.
44    #[error("I/O error: {0}")]
45    #[diagnostic(code(rtb::io))]
46    Io(#[from] std::io::Error),
47
48    /// No registered command matches the user-supplied name.
49    #[error("command not found: {0}")]
50    #[diagnostic(code(rtb::command_not_found), help("run `--help` to list available commands"))]
51    CommandNotFound(String),
52
53    /// A built-in command was requested but its Cargo feature is off.
54    #[error("feature `{0}` is not compiled in")]
55    #[diagnostic(
56        code(rtb::feature_disabled),
57        help("rebuild with the appropriate Cargo feature enabled")
58    )]
59    FeatureDisabled(&'static str),
60
61    /// A downstream crate's typed diagnostic, kept live for rendering.
62    #[error("{0}")]
63    #[diagnostic(transparent)]
64    Other(#[from] Box<dyn Diagnostic + Send + Sync + 'static>),
65}
66
67pub mod hook;