Getting location information from a `thiserror::Error`?

With help from this post I am able to track which ? in a function caused the function to return an error. This is wonderful!

thiserror helps reduce all the boilerplate in producing errors, but the only way I know how to have this feature with a thiserror::Error is to manually impl From. Unless someone else knows a way where the library already provides this functionality for me?

Here is an example

 #[derive(Debug, thiserror::Error)]
pub enum BoardsExportError {
    #[error("{0}")]
    Xlsxwriter(String),
    #[error(transparent)]
    Io(#[from] std::io::Error), // doesn't have loc info
    #[error(transparent)]
    Other(#[from] DynError), // doesn't have loc info
}

/// manual impl to provide loc info
impl From<xlsxwriter::XlsxError> for BoardsExportError {
    #[track_caller]
    fn from(e: xlsxwriter::XlsxError) -> Self {
        let loc = std::panic::Location::caller();
        Self::Xlsxwriter(format!(
            "{e}, {}:{}:{}",
            loc.file(),
            loc.line(),
            loc.column()
        ))
    }
}

Thanks in advance!

1 Like

With thiserror, if you add a backtrace: Backtrace field it'll automatically capture the call stack from where the error was created.

4 Likes

All the methods on Backtrace are nightly only, says the docs. And maybe the struct itself is also nightly only? Do I have this feature on stable Rust?

I guess I could access the location info maybe something like this?

pub enum RandomError {
    #[error("{source} at {backtrace.frames.next().unwrap():?}")]
    A {
        #[from]
        source: ErrorA,
        backtrace: Backtrace,
    }
    B { ... } 
}

I don't want to debug print the entire Backtrace

Does it need to be a std::backtrace::Backtrace, or could you use a backtrace::Backtrace?

The #[error("...")] thing uses the same syntax as format!(), so you would need to use somethnig like #[error("{source} at {}", get_function_name(backtrace))].

1 Like

Oh yes, of course, I can just use that crate! Thanks so much.

Well, backtrace is now stable :slight_smile:

std::backtrace isn't enough, unfortunately. Backtrace support in thiserror also uses other nightly features which cause compiler errors if you try to add a Backtrace to your error: Rust Playground

I can confirm that it also causes errors even if you want to use the 3rd-party backtrace::Backtrace as well.

1 Like

I tried reporting this as an issue, but apparently I am banned from @dtolnay's repositories: :grimacing:

Ah, I made an issue about it when I hit it myself: derive(Error) with Backtrace causes errors on beta · Issue #204 · dtolnay/thiserror · GitHub
Though it looks like that's just the expected behaviour.