# Custom Error Types — Rust

Source: https://www.skillbyai.com/en/rust/e-custom

> Enums that describe what went wrong.

## Display, Error and From

For applications and libraries, define an error **enum** listing the failure cases, implement `Display` (human message) and `std::error::Error`, and implement `From<OtherError>` so `?` converts underlying errors automatically. Crates such as `thiserror` (for libraries) generate this boilerplate, and `anyhow` (for applications) offers a convenient catch-all error type with context.

## An OrderError enum with automatic conversion, run

I ran this with Rust 1.99.0 (cargo run, edition 2024, standard library only). A valid order succeeds; "two" fails to parse and ? converts the ParseIntError into OrderError::InvalidQty through From; the lamp returns OutOfStock. Display produces readable messages.

```rust
use std::fmt;

#[derive(Debug)]
enum OrderError {
    OutOfStock(String),
    InvalidQty(std::num::ParseIntError),
}

impl fmt::Display for OrderError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OrderError::OutOfStock(item) => write!(f, "{item} is out of stock"),
            OrderError::InvalidQty(e) => write!(f, "invalid quantity: {e}"),
        }
    }
}

impl std::error::Error for OrderError {}

impl From<std::num::ParseIntError> for OrderError { // lets ? convert automatically
    fn from(e: std::num::ParseIntError) -> Self { OrderError::InvalidQty(e) }
}

fn order(item: &str, qty: &str) -> Result<String, OrderError> {
    let n: u32 = qty.parse()?;
    if item == "lamp" {
        return Err(OrderError::OutOfStock(item.to_string()));
    }
    Ok(format!("ordered {n} x {item}"))
}

fn main() {
    for (item, qty) in [("pen", "2"), ("pen", "two"), ("lamp", "1")] {
        match order(item, qty) {
            Ok(msg) => println!("{msg}"),
            Err(e) => println!("error: {e}"),
        }
    }
}
```

Output:

```
ordered 2 x pen
error: invalid quantity: invalid digit found in string
error: lamp is out of stock
```

## thiserror for libraries, anyhow for apps

Libraries expose precise error enums; applications often just need context-rich errors to log.

**Quiz:** Why implement From<ParseIntError> for your error type?

- [x] So ? can convert a ParseIntError into your error automatically
- [ ] To print errors in colour
- [ ] To make errors Copy
- [ ] Because Display requires it

*Answer:* So ? can convert a ParseIntError into your error automatically. Conversion powers the ? operator.
