PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Monday, November 14, 2022

[FIXED] How do I print a backtrace without panicking using thiserror?

 November 14, 2022     error-handling, rust, thiserror     No comments   

Issue

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?


Solution

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:

  1. add a backtrace: Backtrace field to your error type.
  2. set the backtrace when you create an error using 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


ASIDE

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.



Answered By - Michael Anderson
Answer Checked By - Marilyn (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing