In this lesson, you will learn how to group diverse error conditions into behavioral categories so your callers can handle failures based on "what went wrong" rather than "what specific type triggered it."
Categorizing Failure by Behavior
When building a library, your functions might encounter many different errors—file system issues, network timeouts, or parsing failures. While your internal code cares about the specific cause, a consumer of your API often only cares about the action they should take: Retry, Abort, or Ignore.
Instead of forcing the caller to match against every individual error variant, you can implement an ErrorKind pattern. This involves adding a method to your error type that maps specific variants into broader, actionable categories.
Concrete Example
Imagine an API that performs web requests. You might have NetworkError, Timeout, and InvalidResponse variants. By using an ErrorKind enum, you simplify the caller’s logic:
pub enum ErrorKind {
Transient, // Issues like timeouts that might succeed if retried
Permanent, // Logic bugs or bad inputs that will never succeed
}
impl MyError {
pub fn kind(&self) -> ErrorKind {
match self {
Self::Timeout => ErrorKind::Transient,
Self::NetworkDown => ErrorKind::Transient,
Self::InvalidData => ErrorKind::Permanent,
}
}
}
Now, when a user calls your function, they don't need to know the intricate details of your error enum. They simply inspect the kind():
match my_api_call() {
Err(e) if matches!(e.kind(), ErrorKind::Transient) => retry_operation(),
Err(e) => fatal_error(e),
Ok(val) => handle(val),
}
Why This Matters
By providing an ErrorKind pattern, you decouple the internal implementation of your error reporting from the decision-making logic of the consumer. As you add more error variants (like DnsResolutionFailed or ServerOverloaded), the caller's code remains unchanged because those new errors simply map to the existing Transient category. This makes your API significantly more robust and easier for others to integrate into their own error-handling strategies.
Key Takeaway: Categorizing errors by behavior using an ErrorKind pattern allows callers to write high-level recovery logic that remains stable even as your underlying error types grow and change.