{"record":{"id":"46a932b73abf0d7d","repo":"openai/codex","slug":"missing-required-environment-variable-env-var","errorCode":null,"errorMessage":"missing required environment variable {env_var}","messagePattern":"missing required environment variable (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"codex-rs/network-proxy/src/mitm_hook.rs","lineNumber":358,"sourceCode":"}\n\nfn compile_injected_header<EnvFn, FileFn>(\n    header: &InjectedHeaderConfig,\n    resolve_env_var: &EnvFn,\n    read_secret_file: &FileFn,\n) -> Result<ResolvedInjectedHeader>\nwhere\n    EnvFn: Fn(&str) -> Option<String>,\n    FileFn: Fn(&AbsolutePathBuf) -> Result<String>,\n{\n    let name = parse_header_name(&header.name)?;\n    let (secret, source) = match (\n        header.secret_env_var.as_deref(),\n        header.secret_file.as_deref(),\n    ) {\n        (Some(env_var), None) => {\n            let value = resolve_env_var(env_var)\n                .ok_or_else(|| anyhow!(\"missing required environment variable {env_var}\"))?;\n            (value, SecretSource::EnvVar(env_var.to_string()))\n        }\n        (None, Some(secret_file)) => {\n            let path = parse_secret_file(secret_file)?;\n            let value = read_secret_file(&path)?;\n            (value, SecretSource::File(path))\n        }\n        _ => {\n            return Err(anyhow!(\n                \"expected exactly one of secret_env_var or secret_file\"\n            ));\n        }\n    };\n\n    let prefix = header.prefix.clone().unwrap_or_default();\n    let value = HeaderValue::from_str(&format!(\"{prefix}{secret}\"))\n        .with_context(|| format!(\"invalid value for injected header {}\", header.name))?;\n","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/network-proxy/src/mitm_hook.rs#L340-L376","documentation":"When a hook injects a header via secret_env_var, compile_injected_header resolves the variable immediately at hook-compile time (proxy startup) through env::var. If the variable is unset, compilation fails with 'missing required environment variable {env_var}', wrapped in the context 'failed to compile injected header {name}'. Secrets are read once at startup, never per request.","triggerScenarios":"An inject_request_headers entry like { name = \"authorization\", secret_env_var = \"MY_TOKEN\" } compiled by compile_mitm_hooks while MY_TOKEN is absent from the proxy process's environment — typical when the proxy is spawned by systemd, a daemon manager, or a different shell than the one where the variable was exported.","commonSituations":"Variable exported interactively but the proxy runs as a service; CI secrets not passed into the job env; typo in the variable name; renaming the var in config but not in the launch environment.","solutions":["Export the variable in the exact environment that starts the network proxy (shell profile, systemd Environment=, or the launcher's env)","Verify presence without printing the value: test -n \"$MY_TOKEN\" && echo set","If the process cannot see environment variables, switch the entry to secret_file with an absolute path to a readable secret file","Check the spelling in secret_env_var character-for-character against the environment"],"exampleFix":"# before — header needs MY_TOKEN but the service env lacks it\n[[network.mitm_hooks.actions.inject_request_headers]]\nname = \"authorization\"\nsecret_env_var = \"MY_TOKEN\"\nprefix = \"Bearer \"\n\n# after — read from an absolute-path file the service can access\n[[network.mitm_hooks.actions.inject_request_headers]]\nname = \"authorization\"\nsecret_file = \"/etc/codex/secrets/my_token\"\nprefix = \"Bearer \"","handlingStrategy":"validation","validationCode":"// Rust — check env secrets before starting the proxy\nfor hook in &config.mitm_hooks {\n    for h in &hook.actions.inject_request_headers {\n        if let Some(name) = &h.secret_env_var {\n            std::env::var(name)\n                .map_err(|_| anyhow!(\"{name} is not set in the proxy environment\"))?;\n        }\n    }\n}","typeGuard":"fn env_secret_available(h: &InjectedHeaderConfig) -> bool {\n    match (&h.secret_env_var, &h.secret_file) {\n        (Some(name), None) => std::env::var(name).is_ok(),\n        (None, Some(_)) => true,\n        _ => false,\n    }\n}","tryCatchPattern":"match compile_mitm_hooks(&config) {\n    Ok(hooks) => { /* proceed */ }\n    Err(err) => eprintln!(\"hook compilation failed: {err:#}\"), // 'failed to compile injected header authorization: missing required environment variable MY_TOKEN'\n}","preventionTips":["Pre-flight every secret_env_var with std::env::var before spawning the proxy","For services/daemons prefer secret_file with an absolute path over env vars","Verify presence with test -n \"$VAR\" — never echo the value into logs","Use the same launch path in CI and production so env parity is real"],"tags":["network","mitm","codex","secrets","environment-variables","startup"],"backgroundTag":"missing-env-var","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}