Skip to content

Commit 035fd45

Browse files
Treat deserialization errors from empty env vars as unset env var
Fixes #35 I'm a bit worried that this might seem too much like magic, but I think this is just the most useful behavior in all situations I can think of. This covers not only Booleans, but also numbers and anything else for which an empty string is not a valid value. It also leaves types with empty strings as valid values untouched. I've been thinking about how this behavior could confuse users. And I could only think of two cases: - A config value has a default value, and the user thinks that empty string is a valid value, when in fact it isn't. Then, setting `FOO=` will result in the default value, when the user expected an empty string. Here, a clear error "empty string invalid" would be more helpful. - A config value with a type that can be deserialized from empty string, but the user thinks it cannot. Maybe the config value is a list of numbers, where "" is just an empty list, but the user thought it was a single number. Then setting `FOO=` means setting the value to an empty list. Not sure if any of these cases will happen often enough or is important enough to not merge this?
1 parent ce3b266 commit 035fd45

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

src/internal.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,18 @@ pub fn from_env_with_parser<T, E: std::error::Error + Send + Sync + 'static>(
6666
parse: fn(&str) -> Result<T, E>,
6767
) -> Result<Option<T>, Error> {
6868
let v = get_env_var!(key, field);
69-
parse(&v)
70-
.map(Some)
71-
.map_err(|err| {
69+
let is_empty = v.is_empty();
70+
match parse(&v) {
71+
Ok(v) => Ok(Some(v)),
72+
Err(_) if is_empty => Ok(None),
73+
Err(err) => Err(
7274
ErrorInner::EnvParseError {
7375
field: field.to_owned(),
7476
key: key.to_owned(),
7577
err: Box::new(err),
7678
}.into()
77-
})
79+
),
80+
}
7881
}
7982

8083
pub fn from_env_with_deserializer<T>(
@@ -83,9 +86,11 @@ pub fn from_env_with_deserializer<T>(
8386
deserialize: fn(crate::env::Deserializer) -> Result<T, crate::env::DeError>,
8487
) -> Result<Option<T>, Error> {
8588
let s = get_env_var!(key, field);
89+
let is_empty = s.is_empty();
8690

8791
match deserialize(crate::env::Deserializer::new(s)) {
8892
Ok(v) => Ok(Some(v)),
93+
Err(_) if is_empty => Ok(None),
8994
Err(e) => Err(ErrorInner::EnvDeserialization {
9095
key: key.into(),
9196
field: field.into(),

0 commit comments

Comments
 (0)