Skip to main content

Crate dotenv

Crate dotenv 

Source
Expand description

Loads environment variables from .env files.

§Quick start

fn main() -> Result<(), dotenv::Error> {
    dotenv::load()?;
    Ok(())
}

Call load near the start of your program to load a .env file from the current working directory.

§Precedence

  • Existing environment variables are never overwritten. A variable already set in the environment takes priority over anything in .env.
  • First declaration wins in .env. If the same key appears multiple times, only the first is used.
  • Loading is atomic. If the file contains a parse error, no environment variable is modified, even for lines that appear before the error.

§Supported syntax

HELLO=world
HELLO="world"
HELLO='world'
HELLO='"nested"'
HELLO=world  # inline comment
# full-line comment

§Key names

Keys may only contain ASCII letters, digits, _, ., and -. A key may start with any of those characters (including a digit, . or -).

§Comments

A # starts an inline comment only when it is preceded by whitespace (K=v # comment strips the comment, but K=v#comment keeps the #).

§Whitespace

Leading whitespace on a line and whitespace around = are ignored. An unquoted value is trimmed; whitespace inside an unquoted value is kept (K=hello world yields hello world).

§Quotes and escapes

  • Single-quoted values ('...') are literal: no escapes are processed.
  • Double-quoted values ("...") process the escape sequences \\, \', \", \$, \n, \t, and \r. Any other backslash sequence is a ParseErrorKind::InvalidEscape error.
  • Backslashes in unquoted values are literal (K=C:\path yields C:\path).
  • A UTF-8 byte-order mark (BOM) at the very start of the file is ignored.

§Limitations

  • Multi-line values are not supported.
  • Variable substitution (e.g. ${FOO}) is not supported.
  • Export syntax (export KEY=value) is not supported.
  • Only \n and \r\n are recognised as line endings; a lone \r is not a line break.
  • Values may not contain a NUL byte (\0), which cannot be placed in the process environment.

§Thread safety

load and from_path call std::env::set_var internally, which is unsound to call while other threads are running or reading the environment. Call them before spawning any threads (typically at the very start of main). If you only need to inspect .env content, use parse, which does not touch the process environment.

§Performance

.env files are configuration-sized. Because the platform setenv costs O(n) per variable once n variables are set, loading an extremely large number of variables is quadratic overall. Do not feed untrusted, arbitrarily large files to load; validate them with parse first.

§Deserializing into structs with FromEnv

This crate provides a FromEnv trait (and a #[derive(FromEnv)] proc-macro) for constructing typed structs directly from environment variables.

§Basic usage

ⓘ
use dotenv::FromEnv;

#[derive(FromEnv)]
struct Config {
    #[env(rename = "MY_HOST")]
    host: String,
    #[env(rename = "MY_PORT")]
    port: u16,
}

let cfg = Config::from_env().unwrap();

§Default values

Use #[env(default)] for any type that implements Default (yields the default when the variable is not set) or #[env(default = expr)] for any type. The environment variable is always read first; the default is only used when it is not set.

ⓘ
#[derive(FromEnv)]
struct Config {
    #[env(rename = "MY_HOST")]
    host: String,
    #[env(rename = "MY_VERBOSE", default)]
    verbose: Option<bool>,
    #[env(default)]
    timeout: u64,             // reads TIMEOUT, falls back to 0
    #[env(rename = "MY_PORT", default = 8080)]
    port: u16,
}

Option<T> fields are always optional: an unset (or empty) variable yields None, otherwise the value is parsed and wrapped in Some.

ⓘ
#[derive(FromEnv)]
struct Config {
    #[env(rename = "MY_PORT")]
    port: Option<u16>,        // None when MY_PORT is unset or empty
}

§Custom parsers

When the standard FromStr parsing is insufficient, provide a custom parser via #[env(with = "func")]. The function may be a full path (module::func) and must have the signature fn(&str, &str) -> Result<T, FromEnvError>:

ⓘ
use dotenv::{FromEnv, FromEnvError};

fn parse_port(_var: &str, val: &str) -> Result<u16, FromEnvError> {
    val.parse().map_err(|e| FromEnvError::invalid("MY_PORT", val, e))
}

#[derive(FromEnv)]
struct Config {
    #[env(rename = "MY_PORT", with = "parse_port")]
    port: u16,
}

§Nested structs

Fields whose type also implements FromEnv are automatically detected and populated as nested structs. The parent’s field name (in SCREAMING_SNAKE_CASE) is used as a prefix so that child fields are read from prefixed variable names:

ⓘ
#[derive(FromEnv)]
struct AppConfig {
    database: Database,
    debug: bool,       // reads DEBUG
}

#[derive(FromEnv)]
struct Database {
    url: String,       // reads DATABASE_URL
    pool_size: u32,    // reads DATABASE_POOL_SIZE
}

§Custom FromEnvValue implementations

For leaf types that need special parsing logic, implement FromEnvValue directly on your type. Types that implement FromStr get a blanket impl automatically.

§Compile-time diagnostics

Invalid usage is reported as an ordinary compile error rather than a macro panic:

ⓘ
use dotenv::FromEnv;

// Tuple structs are not supported.
#[derive(FromEnv)]
struct Config(u16);
ⓘ
use dotenv::FromEnv;

// Multiple `#[env(...)]` attributes on one field are rejected.
#[derive(FromEnv)]
struct Config {
    #[env(rename = "A")]
    #[env(rename = "B")]
    value: u16,
}

#[env(default)] without a rename reads the variable derived from the field name and requires the field type to implement FromEnvAuto (a built-in leaf type, or a nested FromEnv struct); #[env(rename = "...", default)] reads the named variable via FromEnvValue.

§Convenience function

The function from_env lets you avoid importing the trait:

ⓘ
let cfg: Config = dotenv::from_env().unwrap();

Structs§

ParseError
A parse error with the line number and kind.

Enums§

Error
Errors that can occur when loading a .env file.
FromEnvError
Error returned by FromEnv::from_env.
ParseErrorKind
The specific kind of parse error.

Traits§

FromEnv
Trait for types that can be constructed from environment variables.
FromEnvAuto
Auto-dispatch trait for un-attributed #[derive(FromEnv)] fields.
FromEnvValue
Trait for converting a raw env-var string into a typed value.

Functions§

from_env
Convenience function to load a FromEnv type from environment variables.
from_path
Loads a .env file from an explicit path.
load
Loads the .env file from the current working directory.
parse
Parses .env content into a map of key/value pairs.

Derive Macros§

FromEnv