Is std::env::VarError designed like this on purpose, and if so, why?

Hey folks,

use std::env;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    println!("Hello, world! {}", env::var("DOES_NOT_EXIST")?);
    Ok(())
    
}

Running this will yield Error: NotPresent, which does not include information on what environment variable was being accessed. I would've expected this information to be included in the error, as is the case e.g. for VarError::NotUnicode(OsString).

Is this a design oversight, or is this is a case where it makes sense to omit this information and I'm not seeing why? To provide more readable error messages would I then use something like anyhow?


For reference, this is where the error is generated, and it seems fairly straightforward to provide a more useful error here.

fn _var(key: &OsStr) -> Result<String, VarError> {
    match var_os(key) {
        Some(s) => s.into_string().map_err(VarError::NotUnicode),
        None => Err(VarError::NotPresent),
    }
}

I think it just gives you whatever you get from the OS, which is also why file errors don't include the path.

Also, if you are not needing that information (maybe because you know the environment variable you were interested), it would make the error bigger and more expensive to create than necessary.

I've seen (and usually do) people „wrap“ errors into more layers of context, with .context calls from anyhow or other similar crate.

4 Likes