How to customize the `main` error message when returning an `Error`, other concern

I tried to customize it using:

panic::set_hook(Box::new(|panic_info| {...

However it looks like when the main is terminated without a panic, just because a Result <_, Error> is involved, like:

use std::fs::File;
fn main() -> Result<(), Error> {
    let _ = File::open("bar.txt").map_err(|_| err_msg("test"))?;
    Ok(())
}

Some other customization trick should be used. Which one?

PS The default implementation printing an error is probably fine, however it's CGI program and it needs to show a message in a browser, and using stderr doesn't work.

It's very straightforward to handle all errors in main, print them the way you want, and return Ok(()) or call exit. Why would you need something else?

1 Like

I understand that there are tons work around, we will consider them after somebody clearly assured me: no, customization of that is impossible unless you want to rewrite runtime.

When you return an Err(e) from main(), the e is displayed using its Debug impl, so if you want to change how e is displayed, just override that.

Why is handling errors a work around? Error handling is something we do in every function, so why not in main? I think customizing the way main works would be a work around if normal error handling doesn't work (but it does).

So I have to define own Result to be able to customize it, right?

No, just your own error type. You still need to use the standard Result.

To ensure that you don't return an error here (since you don't want it to be printed), define main without a return type (as you would do with any other function):
fn main() {

See the example here:
https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#where-the--operator-can-be-used

Rust calls std::process::Termination::report on values returned from main()[1]. That trait is implemented for Result in std here. I often use a pattern like this:

fn main() {
    if let Err(e) = inner_main() {
        // Implement your custom error printing logic
        // For example:
        log::error!("{e:#?}");
    }
}

fn inner_main() -> Result<(), Error> {
    // You can ergonomically use ? here
    some_fallible_code()?;
    Ok(())
}

  1. Documented in the Reference, and in the docs of Termination ↩︎

3 Likes

This is actually a very good approach with a minimum code change.

This works like a charm. However requires lot code changes to adopt an own error type.

Thanks everyone, we can close the topic.

It looks like you used a String as your error type based on that representation in your screenshot, which is generally discouraged. The main options for an error type are:

  • Box<dyn std::error::Error>: simple, but missing some things (you should probably add Send + Sync bounds, it doesn’t have a backtrace, no chainable error causes, …)
  • anyhow::Error: A “better” version of Box<dyn Error>, with support for context, chains of causes, and backtraces.
  • Custom Error type: also fine, but will likely be one giant enum with tons of variants for every library’s error type. You would probably like to use thiserror for ergonomics.

Also, if your errors are going to be printed out to a user, Display is probably more correct to use than Debug (Debug is for “a programmer-facing, debugging context”, whereas Display is “for user-facing output”).

If you’re done with the topic, you can mark someone’s post as the solution.

2 Likes

Honestly I do not know which error type I use. I use io::Result<()>, and it's a native in most cases. But somewhere I convert to it using map_err when Result is incompatible or it's Option. Since errors are very rare in my case, I do not care much about a perfect processing them. I started worrying about getting some message after the root edited some my files and I didn't notice that until I realized that I lost some work due that. Changes couldn't be saved, but I didn't know that. So just some error message is fine for now. No detail investigation is necessary.

Can I mark several people?

No, only one reply. It's the checkbox at the bottom of the reply.

I will file the site enhancement request then.