CodeBlanks Logo Icon CodeBlanks

Summary - Advanced error handling

Combine thiserror and From to build a config reader error.

Advanced error handling summary

Error types implement Debug + Display + Error. Libraries use concrete enums (thiserror), applications a flexible type (anyhow or Box<dyn Error>). impl From enables automatic conversion with ?. Context (with_context or map_err) makes errors understandable. source() gives the underlying cause of an error and can be walked as a chain.

The error chain

An error type implementing source can give a high-level message without losing the cause:

#[derive(Debug)]
struct UstHata {
    kaynak: ParseIntError,
}

impl fmt::Display for UstHata {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "yapılandırma yüklenemedi")
    }
}

impl Error for UstHata {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        Some(&self.kaynak)
    }
}

The chain is walked with while let Some(k) = s { ..; s = k.source(); }.

Practice Print the chain

Write the UstHata type above. Create an instance with "x".parse::<i32>().unwrap_err(); print the error first, then walk the source chain as neden: MESSAGE.

Starter code

main.rs
use std::error::Error;
use std::fmt;
use std::num::ParseIntError;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::error::Error;
use std::fmt;
use std::num::ParseIntError;

#[derive(Debug)]
struct UstHata {
    kaynak: ParseIntError,
}

impl fmt::Display for UstHata {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "yapılandırma yüklenemedi")
    }
}

impl Error for UstHata {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        Some(&self.kaynak)
    }
}

fn main() {
    let e = UstHata { kaynak: "x".parse::<i32>().unwrap_err() };
    println!("{}", e);
    let mut s = e.source();
    while let Some(k) = s {
        println!("  neden: {}", k);
        s = k.source();
    }
}

Expected output

yapılandırma yüklenemedi
  neden: invalid digit found in string

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What does <code>Error::source</code> return by default?

  • The Display message
  • It panics
  • None Correct answer
  • The error itself

Explanation: Error types with an underlying cause override source to return Some(&inner_error).

2 Give the cause

Question
impl Error for UstHata {
    fn ____(&self) -> Option<&(dyn Error + 'static)> {
        Some(&self.kaynak)
    }
}
Answer
impl Error for UstHata {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        Some(&self.kaynak)
    }
}

Explanation: source returns the underlying error.

3 Group summary

Term Meaning
impl Error Error contract
impl From<E> Conversion with ?
with_context Adds context
source() Underlying cause

All lessons in Intermediate