I am running a Rust warp webserver and I need more descriptive error messages. I'd like to print a backtrace or something similar so I can tell where the error started.
I was using the Failure
crate, but it is now deprecated so I migrated to thiserror
.
Is it possible (without using nightly), to print a backtrace without panicking?
There are ways to get to the backtrace information - but it relies on what are currently "nightly only" APIs. If you're happy to use nightly and stick with thiserror
, here's what you do... (If not then see the ASIDE at the end for other ideas).
If you're creating the error from scratch the steps are:
backtrace: Backtrace
field to your error type.backtrace::force_captue()
If you're creating this error due to another error and want to use its backtrace instead, then just add #[backtrace] to the source
field where you keep the original error.
Then to get the backtrace information you can just use the backtrace()
function on std::Error
.
An example looks like this:
#![feature(backtrace)]
extern crate thiserror;
use std::backtrace::Backtrace;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DataStoreError {
//#[error("data store disconnected")]
//Disconnect(#[from] io::Error),
#[error("the data for key `{0}` is not available")]
Redaction(String),
#[error("invalid header (expected {expected:?}, found {found:?})")]
InvalidHeader {
expected: String,
found: String,
backtrace: Backtrace,
},
#[error("unknown data store error")]
Unknown,
}
pub fn explode() -> Result<(), DataStoreError> {
Err(DataStoreError::InvalidHeader {
expected: "A".to_owned(),
found: "B".to_owned(),
backtrace: Backtrace::force_capture(),
})
}
fn main() {
use std::error::Error;
let e = explode().err().unwrap();
let b = e.backtrace();
println!("e = {}", e);
println!("b = {:#?}", b);
}
This outputs something like:
e = invalid header (expected "A", found "B")
b = Some(
Backtrace [
{ fn: "playground::explode", file: "./src/main.rs", line: 28 },
{ fn: "playground::main", file: "./src/main.rs", line: 34 },
{ fn: "core::ops::function::FnOnce::call_once", file: "/rustc/879aff385a5fe0af78f3d45fd2f0b8762934e41e/library/core/src/ops/function.rs", line: 248 },
...
You can see a working version in the playground
If you're not tied to thiserror
and need to use the stable version of the compiler, you could instead use snafu
which has support for backtraces using the backtrace
crate, rather than std::backtrace
, and so works on stable.
There may also be ways to make thiserror
work with the backtrace
crate rather than std::backtrace
but I've not tried that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With