Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] In {:#?} why is the outermost context called "caused by" and how is Context expected to be used? #324

Open
nathan-at-least opened this issue Oct 26, 2023 · 1 comment

Comments

@nathan-at-least
Copy link

Suppose I have code like this (see this playground):

use anyhow::Context;

fn my_thing(path: &Path, extra_sauce: bool) -> anyhow::Result<()> {
    std_or_some_external_lib::do_other_thing()
        .context(format!("path: {:?}", path.display()))
        .context(format!("extra_sauce: {:?}", extra_sauce))?;
    Ok(())
}

Let's suppose do_other_thing results in an error which displays as failed to do other thing because <reason>

Now what I intend by the code above is "if do_other_thing results in an error, then when describing that error cause to a user, provide this extra context for the user to have more context about the cause", so I would expect to see this kind of output:

Error: failed to do other thing because <reason> 

Context:
    0: path: "/tmp/non-existent"
    1: extra_sauce: true

But for some reason the {:#?} display calls the outermost "the cause" so it shows this output:

Error: extra_sauce: true

Caused by:
    0: path: "/tmp/non-existent"
    1: failed to do other thing because <reason>

This output seems backwards and confusing to me. Am I somehow misunderstanding Context? How should it be used?

It feels like it needs to be used like this in order to have clearer error messages, which seems clunky and redundant:

use anyhow::Context;

fn my_thing(path: &Path, extra_sauce: bool) -> anyhow::Result<()> {
    std_or_some_external_lib::do_other_thing()
        .context(format!("path: {:?}", path.display()))
        .context(format!("extra_sauce: {:?}", extra_sauce))
        .context("failed to do some other thing".to_string())?; // Why am I describing the error of `do_other_thing` which already describes itself?
    Ok(())
}
@nathan-at-least
Copy link
Author

Based on my rereading of Context#example it seems like I need to retrain myself to rename Context::context as Context::caused_by

In other words, arguments to that method should always describe a cause of an error, but not "auxillary context the user should know about the cause". Is that how to think of it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant