valeriansaliou/sonic · error · panic
env_var: variable '{key}' is not set
Error message
env_var: variable '{key}' is not set What it means
Sonic's config deserializer supports ${env.VAR} interpolation in the TOML file. get_env_var panics via std::env::var when the referenced environment variable is not set, aborting config parsing. Helpers affected: str, opt_str, socket_addr, path_buf.
Source
Thrown at core/src/util/serde.rs:118
fn is_env_var(value: &str) -> bool {
Regex::new(r"^\$\{env\.\w+\}$")
.expect("env_var: regex is invalid")
.is_match(value)
}
fn get_env_var(wrapped_key: &str) -> String {
let key: String = String::from(wrapped_key)
.drain(6..(wrapped_key.len() - 1))
.collect();
// NOTE: While we could deprecate the `${env.*}` syntax now that Sonic has
// first-class support for environment variables, it would force people
// to use the Sonic naming convention and potentially duplicate some
// variables. For better UX, let’s keep it that way. It doesn’t require
// dependencies nor bloat the code so it’s acceptable.
std::env::var(&key).unwrap_or_else(|_| panic!("env_var: variable '{key}' is not set"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_checks_environment_variable_patterns() {
assert!(is_env_var("${env.XXX}"));
assert!(!is_env_var("${env.XXX"));
assert!(!is_env_var("${env.XXX}a"));
assert!(!is_env_var("a${env.XXX}"));
assert!(!is_env_var("{env.XXX}"));
assert!(!is_env_var("$env.XXX}"));
assert!(!is_env_var("${envXXX}"));
assert!(!is_env_var("${.XXX}"));
assert!(!is_env_var("${XXX}"));
}View on GitHub (pinned to e6a72da6a5)
Solutions
- Export the missing variable before starting the server (e.g. export CHANNEL_PORT=1491)
- Fix the variable name in the config to match the environment
- Pass the variable through your deployment (docker run -e / k8s env)
- Replace the ${env.*} reference with a literal value
Example fix
// shell
// before
./sonic # config has ${env.SONIC_PASSWORD}, not set
// after
export SONIC_PASSWORD=secret && ./sonic Defensive patterns
Strategy: validation
Validate before calling
// extract every ${env.NAME} from the config and fail fast
for key in extract_env_refs(config_text) {
assert!(
std::env::var(&key).is_ok(),
"missing environment variable: {}",
key
);
} Try / catch
// if you parse config yourself
match std::env::var("CHANNEL_PORT") {
Ok(v) => v,
Err(std::env::VarError::NotPresent) => return Err(format!("env var CHANNEL_PORT not set")),
Err(e) => return Err(e.to_string().into()),
} Prevention
- Source .env before launch or use a process manager that injects env
- Keep a manifest of required env vars and check at container startup
- Avoid ${env.*} for optional values; provide literal defaults
When it happens
Trigger: A config file value like channel = "${env.CHANNEL_PORT}" where CHANNEL_PORT is absent from the process environment when the server starts.
Common situations: Deploying without sourcing an .env file; typos in the variable name; container/orchestrator not injecting the variable; variable defined for the shell but not the service's environment.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- write_buffer for kv must not be zero
- flush_after for kv must be strictly lower than inactive_afte
- max_background_jobs makes max_flushes unneeded, don’t config
- consolidate_after for fst must be strictly lower than inacti
- Cannot find config file at {custom_path:?}
AI-assisted analysis of valeriansaliou/sonic@e6a72da6a5 (2026-09-01).
Data as JSON: /api/errors/96a1d7e05770b70b.
Report an issue: GitHub.