Custom Error Types
In this page:
Defining a Custom Error Enum
A custom error type is typically an enum listing every distinct way an operation can fail, giving callers structured information instead of just a generic string.
Example: Defining a Custom Error Enum
#[derive(Debug)]
enum MathError {
DivideByZero,
NegativeSquareRoot,
}
fn main() {
let err = MathError::DivideByZero;
println!("{:?}", err);
}
Login to try C/C++/Java/PHP code in the editor
Returning a Custom Error from a Function
Functions can return Result<T, MyError> using the custom error type, letting the compiler enforce that every failure case is represented in the enum.
Example: Returning a Custom Error from a Function
#[derive(Debug)]
enum MathError {
DivideByZero,
}
fn divide(a: f64, b: f64) -> Result<f64, MathError> {
if b == 0.0 {
Err(MathError::DivideByZero)
} else {
Ok(a / b)
}
}
fn main() {
println!("{:?}", divide(10.0, 0.0));
}
Login to try C/C++/Java/PHP code in the editor
Implementing Display for Readable Messages
Implementing std::fmt::Display for a custom error type gives it a clean, human-readable message when printed with {} instead of just the raw Debug output.
Example: Implementing Display for Readable Messages
use std::fmt;
#[derive(Debug)]
enum MathError {
DivideByZero,
}
impl fmt::Display for MathError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MathError::DivideByZero => write!(f, "cannot divide by zero"),
}
}
}
fn main() {
let err = MathError::DivideByZero;
println!("{}", err);
}
Login to try C/C++/Java/PHP code in the editor
Matching on a Custom Error
Because a custom error is an enum, callers can match on it to respond differently to each specific kind of failure, rather than only having a single generic error message.
Example: Matching on a Custom Error
#[derive(Debug)]
enum MathError {
DivideByZero,
NegativeSquareRoot,
}
fn check(n: f64) -> Result<f64, MathError> {
if n < 0.0 {
Err(MathError::NegativeSquareRoot)
} else {
Ok(n.sqrt())
}
}
fn main() {
match check(-4.0) {
Ok(v) => println!("Root: {}", v),
Err(MathError::NegativeSquareRoot) => println!("Cannot take root of negative number"),
Err(MathError::DivideByZero) => println!("Divide by zero"),
}
}
Login to try C/C++/Java/PHP code in the editor
- Using
Stringfor every error instead of a proper enum, losing the ability for callers to match on specific failure kinds. - Forgetting to implement
std::fmt::Display(and oftenstd::error::Error) so the custom error type prints nicely and interoperates with other error-handling code. - Defining a custom error enum but never deriving or implementing
Debug, which most error-handling code expects.
- A custom error type is usually an enum with one variant per distinct kind of failure.
- Implementing
std::fmt::Displaygives the error type a readable, user-facing message. - Implementing
std::error::Errorlets your custom error interoperate with the wider Rust error-handling ecosystem. - Custom error types let callers
matchon specific failure kinds instead of just a generic message string.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: