# Helper for passing extra context to Errors

**URL:** <https://internals.rust-lang.org/t/helper-for-passing-extra-context-to-errors/20259>\
**Category:** libs\
**Created:** [February 4, 2024, 11:08am UTC](https://internals.rust-lang.org/t/helper-for-passing-extra-context-to-errors/20259 "2024-02-04T11:08:56Z")\
**Posts on this page:** 1\
**Showing post:** 11

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [February 6, 2024, 4:32am UTC](https://internals.rust-lang.org/t/helper-for-passing-extra-context-to-errors/20259/11 "2024-02-06T04:32:36Z")

</div>

Here's how I tend to do it already: defer the expensive parts until the implicit `into` and/or until you actually display things. And `From<(SrcErrWithContext, &CheapThing)>` is often a part of that.

Adapted from a project:

```rust
pub struct FileReadError {
    path: PathBuf,
    kind: FileReadErrorKind,
}

enum FileReadErrorKind {
    Open(io::Error), // io::Error is too general, so these
    Read(io::Error), // supply more context
    Parse(FileLineError),
}

```

The expensive parts:

```rust
impl From<(FileReadErrorKind, &Path)> for FileReadError {
    fn from((kind, path): (FileReadErrorKind, &Path)) -> Self {
        let path = path.to_owned();
        Self { path, kind }
    }
}

impl Error for FileReadError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        // (return the io::Error etc .. xor include them in Display below)
    }
}

impl fmt::Display for FileReadError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use FileReadErrorKind as Kind;
        match self.kind {
            Kind::Open(_) => write!(f, "could not open {} for reading", self.path.display()),
            // ...
        }
    }
}

```

What using the infrastructure looks like:

```rust
pub fn open(path: &Path) -> Result<Self, FileReadError> {
    use FileReadErrorKind as Kind;
    // Today / with zip_err
    let file = File::open(path).map_err(|e| (Kind::Open(e), path))?;
    let file = File::open(path).map_err(Kind::Open).zip_err(path)?;
    // ...

    // Today / with zip_err
    this.read_inner(file).map_err(|e| (e, path))?;
    this.read_inner(file).zip_err(path)?;

    Ok(this)
}
fn read_inner(&mut self, mut file: File) -> Result<(), FileReadErrorKind> {
    // ...
}

```

---

_[View the full topic](https://internals.rust-lang.org/t/helper-for-passing-extra-context-to-errors/20259)._
