config-rs icon indicating copy to clipboard operation
config-rs copied to clipboard

Question: why this unwrap throws?

Open AndrewSav opened this issue 8 years ago • 6 comments

extern crate config;

use std::collections::HashMap;

fn main() {

	let mut settings = config::Config::default();
	let file = config::File::with_name("bla");
	{
		let result = settings.merge(file);

		match result {
			Ok(_) => (),
			Err(e) => {
					println!("{:?}",e);
					println!("Failed to read the settings file, skipping...");
			}
		}
	}
	settings.merge(config::Environment::with_prefix("bla")).unwrap();
	println!("{:?}", settings.try_into::<HashMap<String, String>>().unwrap());
}

The Environment::with_prefix unwrap panics. Why does it? Output:

configuration file "bla" not found
Failed to read the settings file, skipping...
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: configuration file "bla" not found', src\libcore\result.rs:906:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: process didn't exit successfully: `target\debug\vault-unseal.exe` (exit code: 101)

AndrewSav avatar Dec 31 '17 05:12 AndrewSav

The source is not checked for errors when you merge. I'd say this is an oversight and should be corrected.

mehcode avatar Jan 26 '18 16:01 mehcode

I disagree. Result of merging several depends on each individual merge being successful. We should not silently drop failed merges as they affect final result. However, intention of the author appears to be to read config from the file exactly once and merge if it is successful. It could be done this way:

extern crate config;

use std::collections::HashMap;

fn main() {

    let mut settings = config::Config::default();
    let file = config::File::with_name("bla");
    {
        let mut file_settings = config::Config::default();
        let result = file_settings.merge(file).map(|_| ());

        match result {
            Ok(()) => { settings.merge(file_settings).unwrap(); },
            Err(e) => {
                    println!("{:?}",e);
                    println!("Failed to read the settings file, skipping...");
            }
        }
    }
    settings.merge(config::Environment::with_prefix("bla")).unwrap();
    println!("{:?}", settings.try_into::<HashMap<String, String>>().unwrap());
}

geniusisme avatar Aug 09 '18 18:08 geniusisme

We're saying mostly the same thing. Hm. And re-reading what's going I take back what I said too. Errors are checked when a source is merged in. However that erroring source is permanently kept in the source list. That's definitely a bug and should be fixed.


To clear up why later .merge calls are failing – the code in .merge currently just uses .refresh which actually re-pulls all config from all sources. It should be improved to only append the latest source instead of rebuilding the stack each time.

mehcode avatar Aug 09 '18 18:08 mehcode

that erroring source is permanently kept in the source list

Yes. That's what I perceive as a problem too.

AndrewSav avatar Aug 09 '18 23:08 AndrewSav

Is this still relevant as of 0.11?

matthiasbeyer avatar Mar 26 '21 16:03 matthiasbeyer

If it was not fixed it is still relevant. The same code when runs with 0.11 produces the same output.

AndrewSav avatar Mar 26 '21 20:03 AndrewSav