{"record":{"id":"96a1d7e05770b70b","repo":"valeriansaliou/sonic","slug":"env-var-variable-key-is-not-set","errorCode":null,"errorMessage":"env_var: variable '{key}' is not set","messagePattern":"env_var: variable '(.+?)' is not set","errorType":"validation","errorClass":"panic","httpStatus":null,"severity":"error","filePath":"core/src/util/serde.rs","lineNumber":118,"sourceCode":"\n    fn is_env_var(value: &str) -> bool {\n        Regex::new(r\"^\\$\\{env\\.\\w+\\}$\")\n            .expect(\"env_var: regex is invalid\")\n            .is_match(value)\n    }\n\n    fn get_env_var(wrapped_key: &str) -> String {\n        let key: String = String::from(wrapped_key)\n            .drain(6..(wrapped_key.len() - 1))\n            .collect();\n\n        // NOTE: While we could deprecate the `${env.*}` syntax now that Sonic has\n        //   first-class support for environment variables, it would force people\n        //   to use the Sonic naming convention and potentially duplicate some\n        //   variables. For better UX, let’s keep it that way. It doesn’t require\n        //   dependencies nor bloat the code so it’s acceptable.\n\n        std::env::var(&key).unwrap_or_else(|_| panic!(\"env_var: variable '{key}' is not set\"))\n    }\n\n    #[cfg(test)]\n    mod tests {\n        use super::*;\n\n        #[test]\n        fn it_checks_environment_variable_patterns() {\n            assert!(is_env_var(\"${env.XXX}\"));\n            assert!(!is_env_var(\"${env.XXX\"));\n            assert!(!is_env_var(\"${env.XXX}a\"));\n            assert!(!is_env_var(\"a${env.XXX}\"));\n            assert!(!is_env_var(\"{env.XXX}\"));\n            assert!(!is_env_var(\"$env.XXX}\"));\n            assert!(!is_env_var(\"${envXXX}\"));\n            assert!(!is_env_var(\"${.XXX}\"));\n            assert!(!is_env_var(\"${XXX}\"));\n        }","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/valeriansaliou/sonic/blob/e6a72da6a532bc3f31d7d93ef1e0964a1a5d01b2/core/src/util/serde.rs#L100-L136","documentation":"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.","triggerScenarios":"A config file value like channel = \"${env.CHANNEL_PORT}\" where CHANNEL_PORT is absent from the process environment when the server starts.","commonSituations":"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.","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"],"exampleFix":"// shell\n// before\n./sonic  # config has ${env.SONIC_PASSWORD}, not set\n// after\nexport SONIC_PASSWORD=secret && ./sonic","handlingStrategy":"validation","validationCode":"// extract every ${env.NAME} from the config and fail fast\nfor key in extract_env_refs(config_text) {\n    assert!(\n        std::env::var(&key).is_ok(),\n        \"missing environment variable: {}\",\n        key\n    );\n}","typeGuard":null,"tryCatchPattern":"// if you parse config yourself\nmatch std::env::var(\"CHANNEL_PORT\") {\n    Ok(v) => v,\n    Err(std::env::VarError::NotPresent) => return Err(format!(\"env var CHANNEL_PORT not set\")),\n    Err(e) => return Err(e.to_string().into()),\n}","preventionTips":["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"],"tags":["env","config","panic","environment-variable"],"backgroundTag":"missing-env-var","analyzedSha":"e6a72da6a532bc3f31d7d93ef1e0964a1a5d01b2","analyzedAt":"2026-09-01T14:10:00.384Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T20:17:18.057Z"}