openai/codex · error

environment variable `{env_var_name}` is empty

Error message

environment variable `{env_var_name}` is empty

What it means

The same token reader as the not-set case (read_remote_auth_token_from_env_var_with), reached when the variable exists but its value trims to zero length (auth_token.trim()). codex rejects blank tokens up front because an empty credential would only fail later at the remote server, far from the actual cause.

Source

Thrown at codex-rs/cli/src/main.rs:2550

    mode: AppServerRemoteControlMode,
) -> anyhow::Result<()> {
    let output = codex_app_server_daemon::set_remote_control(mode).await?;
    println!("{}", serde_json::to_string(&output)?);
    Ok(())
}

fn read_remote_auth_token_from_env_var_with<F>(
    env_var_name: &str,
    get_var: F,
) -> anyhow::Result<String>
where
    F: FnOnce(&str) -> Result<String, std::env::VarError>,
{
    let auth_token = get_var(env_var_name)
        .map_err(|_| anyhow::anyhow!("environment variable `{env_var_name}` is not set"))?;
    let auth_token = auth_token.trim().to_string();
    if auth_token.is_empty() {
        anyhow::bail!("environment variable `{env_var_name}` is empty");
    }
    Ok(auth_token)
}

fn read_remote_auth_token_from_env_var(env_var_name: &str) -> anyhow::Result<String> {
    read_remote_auth_token_from_env_var_with(env_var_name, |name| std::env::var(name))
}

async fn run_interactive_tui(
    mut interactive: TuiCli,
    remote: Option<String>,
    remote_auth_token_env: Option<String>,
    arg0_paths: Arg0DispatchPaths,
) -> std::io::Result<AppExitInfo> {
    if let Some(prompt) = interactive.prompt.take() {
        // Normalize CRLF/CR to LF so CLI-provided text can't leak `\r` into TUI state.
        interactive.prompt = Some(prompt.replace("\r\n", "\n").replace('\r', "\n"));
    }

View on GitHub (pinned to 339751715c)

Solutions

  1. Set a real value: `export CODEX_REMOTE_TOKEN=<token>`.
  2. When sourcing from a file, fail fast on empty: `test -s token.txt || exit 1` before exporting.
  3. In CI, assert the secret is non-empty before the codex step runs.

Example fix

# before
export CODEX_REMOTE_TOKEN=$(cat /missing/path)   # captures nothing -> empty
codex --remote wss://host --remote-auth-token-env CODEX_REMOTE_TOKEN
# after
export CODEX_REMOTE_TOKEN=$(cat /path/to/token)      # non-empty after trim
test -n "$CODEX_REMOTE_TOKEN" || exit 1
Defensive patterns

Strategy: validation

Validate before calling

token_is_blank() { [[ -z ${1//[[:space:]]/} ]]; }
if token_is_blank "${CODEX_REMOTE_TOKEN:-}"; then
  echo "CODEX_REMOTE_TOKEN is blank; refusing to start codex" >&2; exit 2
fi
codex --remote wss://exec.example.com --remote-auth-token-env CODEX_REMOTE_TOKEN

Try / catch

if ! codex --remote wss://host --remote-auth-token-env CODEX_REMOTE_TOKEN 2>err.log; then
  grep -q 'environment variable `CODEX_REMOTE_TOKEN` is empty' err.log && exit 2   # set a real value, then rerun
  exit 1
fi

Prevention

When it happens

Trigger: `export CODEX_REMOTE_TOKEN=''` (or a whitespace-only value) combined with `codex --remote ... --remote-auth-token-env CODEX_REMOTE_TOKEN`.

Common situations: CI secret defined but empty (not yet created, or masked to blank); `VAR=` with no value in a .env file; `export TOKEN=$(cat missing-file)` capturing nothing; a secret manager returning an empty string.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/174f1ef153878eff. Report an issue: GitHub.