this post was submitted on 20 Mar 2026
10 points (100.0% liked)

Rust Programming

9206 readers
8 users here now

founded 7 years ago
MODERATORS
 

Always had the problem that if I wanted to just log an error, rather than bubble it all the way up to main(), that you wouldn't get a stacktrace. You could iterate the source chain and plug the stacktrace together yourself, but it's rather complex code.

Now I realized, you can do this to get a stacktrace:

let error = todo!("Get an error somehow...");
let error = anyhow::anyhow!(error); //converts to an `anyhow::Error`
eprintln!("Error with stacktrace: {error:?}");

For converting to an anyhow::Error, it often also makes sense to use anyhow::Context like so:

use anyhow::Context;
let error = error.context("Deleting file failed.");
you are viewing a single comment's thread
view the rest of the comments
[โ€“] Ephera@lemmy.ml 0 points 4 days ago (1 children)

I've kind of standardized on writing it as "Failed to bar when beebbooping, while fadoodling."

Maybe a more concrete example:

Failed to write file when persisting audio, while recording. Caused by: Permission denied.

The while-part is optional, in case you've got a larger context.
Well, so is the rest of it, really. I may just write "Error when beebbooping", if I believe the error from .bar() to describe itself rather well. Error handling is hard. ๐Ÿซ 

But yeah, you kind of have to describe that an error occurred, rather than purely describing what you want to do, because anyhow doesn't prefix it or such.

I just optimized the context messages and I'm now happy with:

Error: Execute command: redo workspace/motd.json

Caused by:
    0: using sqlite db 'workspace/.redo3.db'
    1: clear dependencies for motd.json
    2: attempt to write a readonly database
    3: Error code 8: attempt to write a readonly database

The "0" context is especially important because it tells you which file is read-only. Here is the code for that:

pub(crate) fn start(mut self) -> Result<DoFileExecution> {
    let rc_folder = self.target.path.parent().unwrap_or(Utf8Path::new("."));
    let mut db = Db::try_open(rc_folder);
    db.transaction(|tx| {
        tx.clear_dependencies(self.target.basename())
            .with_context(|| format!("using sqlite db '{}'", rc_folder.join(DB_FILENAME)))
    })?;

    let now = chrono::Utc::now();
    ...

I don't think something like "failed to clear dependencies using sqlite db '{}'" would be helpful. Something like "failed to" or "error when" does not really add any information. Just describe what is happening. Also, the "clear dependencies" would be redundant because that function can handle that part itself (see msg 1).