Skip to content

Error Handling

  • Crate error type: Error enum derived with thiserror::Error.
  • Result alias: pub type Result<T> = std::result::Result<T, Error>.
  • Propagation: use ? operator. Never unwrap(), expect(), or panic!() in library code.
  • Binary: main() returns ExitCode; delegates to run() -> Result. On Err, the binary renders the error to stderr in the format selected by --format / TTY (below).

The crate emits errors for two consumers from one Error value: the human (the thiserror Display, unchanged) and the LLM agent (a serializable application/problem+json envelope). The envelope type is ProblemDetails in crates/problem.rs, re-exported from the crate root alongside Applicability, CodeAction, SuggestedFix, and OutputFormat. Map any error with Error::to_problem(); render for a format with Error::render(OutputFormat).

Envelope members (ProblemDetails):

FieldRFC 9457 roleNotes
typestandardStable, version-embedded URI (.../v1).
titlestandardShort summary, stable per type.
statusstandardNumeric status class.
detailstandardThis-occurrence text; equals the Display string.
instancestandardurn: occurrence reference.
retry_afteragent extensionDelta-seconds, or null (serialized) on non-transient errors.
suggested_fixagent extension{ description, applicability }, or null.
code_actionsagent extensionArray of LSP-CodeAction-shaped { title, kind, applicability }.
exit_codeoptional extensionProcess exit code; omitted from JSON when absent.

Applicability markers (on every suggested_fix and code_action): machine_applicable (auto-apply), maybe_incorrect (escalate to human), has_placeholders (fill slots first), unspecified (default; treat as maybe_incorrect).

Type URIs (one per variant, distinct, versioned): InvalidInputhttps://zircote.com/rust-template/errors/invalid-input/v1; OperationFailedhttps://zircote.com/rust-template/errors/operation-failed/v1. A breaking change ships a new version rather than redefining the existing one. The base is a single configurable constant, ERROR_TYPE_BASE_URI (derived URI = {base}/{slug}/{version}); adopters point it at their own docs host. Each URI is dereferenceable — it resolves to a per-type reference page under docs/reference/errors/ (the canonical source). The instance URN namespace tracks CARGO_PKG_NAME.

Format selection (OutputFormat::select(explicit, is_terminal)): JSON when --format=json or (no flag and stderr is not a TTY); pretty otherwise. Pretty output is byte-identical to the historical Error: {e} line.

For the rationale, see the Dual-Consumer Error Output explanation doc (docs/explanation/error-architecture.md).