You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Wrapping anyhow::Error in another error loses backtrace #174
//! Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error
It used to be possible to work around this issue in failure (even on stable, which we are on).
It would seem fine if the backtrace could only be propagated if coming from anyhow.
Is it possible to achieve something like this with the anyhow/thiserror combination?
I found one solution for this problem - add the #[backtrace] attribute to inner anyhow::Error, but it requires a nightly.
By the way, map() is lazy and your test never will pass as there indeed would be two different backtraces generated during next() call. I fixed it by switching to Vec.
This seems to be similar to #157; because std::error::Error doesn't currently provide a backtrace() API on stable, that can be forwarded from anyhow to thiserror and back to anyhow. There's a mention about the new nightly provide() API in the docs now that should be able to forward it though:
If a field is both a source (named source, or has #[source] or #[from] attribute) and is marked #[backtrace], then the Error trait’s provide() method is forwarded to the source’s provide so that both layers of the error share the same backtrace. The #[backtrace] attribute requires a nightly compiler with Rust version 1.73 or newer.
So you might need to add both #[from] #[backtrace] to your tuple member (or name it source) as long as you're using a nightly compiler.
There are a few more things at play here that could have printed the backtrace though (without calling anyhow::Error::backtrace()). Calling to_string(), i.e. Display on anyhow::Error will only Display-print the top-level error. Anyhow requires either alt-mode Display printing ({err:#}) or non-alt mode Debug printing ({err:?}) to print .source() errors, and I wouldn't be surprised if it uses the same logic to decide whether to print the backtrace() or not.
That way, calling .unwrap() or returning anyhow::Error out of fn main() which both call Debug on the top-level anyhow::Error, will walk the chain of .source() errors and call Display on those (which will prevent them from also printing their own .source() stack again if they were also anyhow::Error).
Activity
mhnap commentedon Aug 28, 2024
I found one solution for this problem - add the
#[backtrace]attribute to inneranyhow::Error, but it requires a nightly.By the way,
map()is lazy and your test never will pass as there indeed would be two different backtraces generated duringnext()call. I fixed it by switching toVec.Would be great if this could be solved on stable too.
MarijnS95 commentedon Dec 11, 2025
This seems to be similar to #157; because
std::error::Errordoesn't currently provide abacktrace()API on stable, that can be forwarded fromanyhowtothiserrorand back toanyhow. There's a mention about the new nightlyprovide()API in the docs now that should be able to forward it though:https://docs.rs/thiserror/latest/thiserror/
So you might need to add both
#[from] #[backtrace]to your tuple member (or name itsource) as long as you're using anightlycompiler.There are a few more things at play here that could have printed the backtrace though (without calling
anyhow::Error::backtrace()). Callingto_string(), i.e.Displayonanyhow::Errorwill onlyDisplay-print the top-level error. Anyhow requires either alt-modeDisplayprinting ({err:#}) or non-alt modeDebugprinting ({err:?}) to print.source()errors, and I wouldn't be surprised if it uses the same logic to decide whether to print thebacktrace()or not.That way, calling
.unwrap()or returninganyhow::Errorout offn main()which both callDebugon the top-levelanyhow::Error, will walk the chain of.source()errors and callDisplayon those (which will prevent them from also printing their own.source()stack again if they were alsoanyhow::Error).