miette
Fancy diagnostic reporting for Rust errors, with pretty-printed source spans, help text, and error codes.
Repository Health
Technical Analysis
miette is a diagnostic library for Rust that extends std::error::Error with rich, structured error reporting. It defines a Diagnostic trait/protocol that lets error types carry error codes, help text, severity levels, related errors, and labeled source-code spans, and pairs with a derive macro so most of that metadata can be declared directly on thiserror-style error enums.
It ships a default ReportHandler that renders diagnostics as graphical, ANSI/Unicode-aware output with underlined source snippets and cause chains, plus a JSON handler and a narratable, screen-reader-friendly handler that engages automatically under NO_COLOR, CLICOLOR, or CI. It also offers eyre-/anyhow-style Result, Report, and miette! macros for application code, while remaining a plain std::error::Error implementer that libraries can depend on without pulling in the fancy feature.
What You Get
- A Diagnostic trait and derive macro for attaching codes, help text, severity, URLs, and labeled spans to error types.
- A default graphical ReportHandler with ANSI/Unicode snippet rendering, cause-chain printing, and customizable theming.
- Narratable and JSON report handlers for screen readers, CI logs, and machine consumption.
- eyre/anyhow-style Result, Report, and miette! macro for quick application-level error handling.
- Optional syntect-based syntax highlighting for source snippets via the syntect-highlighter feature.
Common Use Cases
- Building CLI tools that need polished, pointed-to error output for end users.
- Writing parsers or compilers that want labeled source-span diagnostics.
- Defining library error types with thiserror and Diagnostic for downstream rich rendering.
- Producing screen-reader- or CI-friendly diagnostic text without ANSI graphics.
Under The Hood
Architecture
The crate splits into a thin protocol layer (protocol.rs, diagnostic_impls.rs) defining the Diagnostic trait and its blanket impls, a set of interchangeable ReportHandler implementations under handlers/ (graphical.rs, narratable.rs, json.rs, debug.rs) selected via miette::set_hook, and a separate eyreish/ module that reimplements an eyre-style boxed error wrapper (error.rs, wrapper.rs, ptr.rs) to provide the Result/Report/miette! ergonomics without depending on the eyre crate itself. Highlighting is factored into a highlighters/ trait with a no-op blank.rs default and an optional syntect.rs implementation, so the fancy graphical path composes a handler, a theme, and a highlighter independently. The companion miette-derive crate is a separate proc-macro workspace member that parses #[diagnostic(...)]/#[label]/#[related] attributes and generates the trait impls the runtime crate consumes, keeping macro expansion isolated from the core library.
Tech Stack
Core dependencies are minimal and mostly optional: unicode-width and cfg-if are always pulled in, while owo-colors, textwrap, supports-hyperlinks, supports-color, supports-unicode, backtrace/backtrace-ext, and terminal_size are gated behind the fancy/fancy-no-backtrace feature flags so non-fancy consumers stay lightweight; syntect is gated separately behind syntect-highlighter. The derive macro depends on syn/quote/proc-macro2 in the usual proc-macro pattern. Dev-dependencies bring in thiserror for example error types, trybuild for compile-fail testing of the derive macro, and serde/serde_json for JSON-handler tests. The crate targets Rust 2018 edition with an MSRV of 1.82.
Code Quality
The crate has an extensive tests/ suite (20+ files) covering the derive macro’s attribute surface (test_derive_attr.rs, test_derive_collection.rs), each report handler’s rendered output (graphical.rs, narrated.rs, color_format.rs), and eyre-style ergonomics (test_context.rs, test_downcast.rs, test_boxed.rs), plus trybuild-driven compile-fail tests via compiletest.rs. lib.rs opts into #![deny(missing_docs, missing_debug_implementations, nonstandard_style)], and a GitHub Actions CI workflow runs the test suite; a clippy.toml and rustfmt.toml configure linting and formatting conventions. Error handling throughout favors typed, explicit Results over panics outside of test/example code.
What Makes It Unique
Unlike anyhow/eyre, which focus purely on error propagation ergonomics, miette treats error presentation as a first-class protocol: diagnostics can declare labeled spans into arbitrary SourceCode, get rendered with cause chains and syntax highlighting in “fancy” terminals, and automatically degrade to a narratable, screen-reader-friendly format under NO_COLOR/CI without any caller code change. Because it remains a plain std::error::Error implementer at its core, library authors can adopt the Diagnostic derive without forcing the fancy rendering dependencies onto every downstream consumer, letting the same error type serve both plain and richly rendered contexts.