{"record":{"id":"1059b5383f84c3d4","repo":"openai/codex","slug":"environment-variable-env-var-for-mcp-server-se","errorCode":null,"errorMessage":"Environment variable {env_var} for MCP server '{server_name}' is empty","messagePattern":"Environment variable (.+?) for MCP server '(.+?)' is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"codex-rs/codex-mcp/src/rmcp_client.rs","lineNumber":842,"sourceCode":"    }\n}\n\nfn is_untrusted_connector_meta_key(key: &str) -> bool {\n    UNTRUSTED_CONNECTOR_META_KEYS.contains(&key)\n}\n\nfn resolve_bearer_token(\n    server_name: &str,\n    bearer_token_env_var: Option<&str>,\n) -> Result<Option<String>> {\n    let Some(env_var) = bearer_token_env_var else {\n        return Ok(None);\n    };\n\n    match env::var(env_var) {\n        Ok(value) => {\n            if value.is_empty() {\n                Err(anyhow!(\n                    \"Environment variable {env_var} for MCP server '{server_name}' is empty\"\n                ))\n            } else {\n                Ok(Some(value))\n            }\n        }\n        Err(env::VarError::NotPresent) => Err(anyhow!(\n            \"Environment variable {env_var} for MCP server '{server_name}' is not set\"\n        )),\n        Err(env::VarError::NotUnicode(_)) => Err(anyhow!(\n            \"Environment variable {env_var} for MCP server '{server_name}' contains invalid Unicode\"\n        )),\n    }\n}\n\nfn validate_mcp_server_name(server_name: &str) -> Result<()> {\n    let re = regex_lite::Regex::new(r\"^[a-zA-Z0-9_-]+$\")?;\n    if !re.is_match(server_name) {","sourceCodeStart":824,"sourceCodeEnd":860,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/codex-mcp/src/rmcp_client.rs#L824-L860","documentation":"Thrown while starting an MCP server whose config declares bearer_token_env_var for the streamable-http transport. resolve_bearer_token found the variable in the process environment, but its value is the empty string. An empty Bearer credential can never authenticate, so Codex fails the server at startup instead of sending a guaranteed-401 request later.","triggerScenarios":"config.toml contains [mcp_servers.NAME] with streamable_http transport and bearer_token_env_var = \"FOO_TOKEN\", and the process launching Codex exports FOO_TOKEN as empty (FOO_TOKEN= codex, an .env line 'FOO_TOKEN=', a CI secret defined but unset, docker-compose '- FOO_TOKEN='). Hit only when the token is resolved host-side, i.e. the server runs in the local environment or the executor does not advertise http_header_env_vars.","commonSituations":"CI pipeline references a secret never configured on the runner; compose/direnv files with a trailing '=' and no value; a secret-name typo so the platform injects an empty placeholder; a login script that exports the variable before fetching the token.","solutions":["Export a real value: FOO_TOKEN=<actual-token> codex (or put it in the shell profile / .env the launcher reads) and restart so the MCP server retries startup","Grep launch files for an empty assignment: grep -rn 'FOO_TOKEN=$' ~/.bashrc .env docker-compose.yml, and fill in the value","If this server does not use bearer auth, delete bearer_token_env_var from its [mcp_servers.NAME] entry","If the token should come from the remote executor, configure it in the executor environment (which must advertise http_header_env_vars) instead of the local one"],"exampleFix":"# before (.env)\nFOO_TOKEN=\n\n# after\nFOO_TOKEN=ghp_0123456789abcdef","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# Fail fast before Codex ever starts the MCP server\n: \"${FOO_TOKEN:?FOO_TOKEN must be set and non-empty for MCP server 'foo'}\"\nif [ -z \"$FOO_TOKEN\" ]; then echo \"FOO_TOKEN is empty\" >&2; exit 1; fi\nexec codex \"$@\"","typeGuard":null,"tryCatchPattern":"let token = resolve_bearer_token(server, bearer_env).map_err(StartupOutcomeError::from);\nif let Err(err) = &token {\n    if err.to_string().contains(\"is empty\") {\n        // env var exists but holds \"\" - surface a 'set the secret' setup message\n    }\n}","preventionTips":["Treat empty secrets as missing: assert non-empty in launch scripts and CI before starting Codex","Use set -u and :? parameter expansion in wrapper scripts","Add a preflight that reads every bearer_token_env_var in config.toml and verifies presence and non-empty","Prefer executor-owned token resolution for cloud-run servers so the local shell env cannot cause this"],"tags":["mcp","codex","environment-variable","bearer-token","authentication","streamable-http","config"],"backgroundTag":"empty-environment-variable","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}