gitbutlerapp/gitbutler · error

Environment variable OPENAI_API_KEY is not set

Error message

Environment variable OPENAI_API_KEY is not set

What it means

Thrown by `openai_env_var_creds` when the `OPENAI_API_KEY` environment variable is not present. This is the last fallback credential source for the OpenAI provider; if the variable is unset, there is no credential and the provider raises this anyhow error before any network call.

Solutions

  1. Set the variable: export OPENAI_API_KEY=sk-...
  2. For GUI-launched apps, set the key at the system/session level so child processes inherit it
  3. In Docker/CI, pass the variable explicitly (docker run -e / CI secret)
  4. Or store the key in GitButler settings / log in for the proxied provider instead

Example fix

// before
$ cargo run -- ai ...
Error: Environment variable OPENAI_API_KEY is not set

// after
$ export OPENAI_API_KEY=sk-proj-...
$ cargo run -- ai ...
Defensive patterns

Strategy: validation

Validate before calling

fn have_openai_key() -> bool {
    std::env::var_os("OPENAI_API_KEY")
        .map(|v| !v.is_empty())
        .unwrap_or(false)
}

Try / catch

match result {
    Err(e) if e.to_string().contains("OPENAI_API_KEY") => {
        eprintln!("export OPENAI_API_KEY=sk-... and retry");
    }
    r => r?,
}

Prevention

When it happens

Trigger: `std::env::var_os("OPENAI_API_KEY")` returns None during credential resolution — the variable is undefined in the environment of the process invoking the provider.

Common situations: Running in a shell/CI without the export; key set for the user but not for a GUI-launched process; variable named differently (e.g. OPENAI_KEY); Docker container launched without -e OPENAI_API_KEY.

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


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/a71dec370e43fe00. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-llm/src/openai.rs:102

            .ok_or(anyhow::anyhow!(
                "No GitButler token available. Log-in to use the GitButler OpenAI provider"
            ))?;
        Ok((CredentialsKind::GitButlerProxied, creds))
    }

    fn openai_own_key_creds() -> Result<(CredentialsKind, Sensitive<String>)> {
        let creds = secret::retrieve(AI_OPENAI_SECRET_HANDLE, secret::Namespace::Global)?.ok_or(
            anyhow::anyhow!(
                "No OpenAI own key configured. Add this through the GitButler settings"
            ),
        )?;
        Ok((CredentialsKind::OwnOpenAiKey, creds))
    }

    fn openai_env_var_creds() -> Result<(CredentialsKind, Sensitive<String>)> {
        let creds = Sensitive(
            std::env::var_os("OPENAI_API_KEY")
                .ok_or(anyhow::anyhow!(
                    "Environment variable OPENAI_API_KEY is not set"
                ))?
                .into_string()
                .map_err(|_| anyhow::anyhow!("Invalid UTF-8 in OPENAI_API_KEY"))?,
        );
        Ok((CredentialsKind::EnvVarOpenAiKey, creds))
    }
}

impl OpenAIClientProvider for OpenAiProvider {
    fn client(&self) -> Result<Client<OpenAIConfig>> {
        match &self.credentials {
            (CredentialsKind::EnvVarOpenAiKey, _) => {
                let config = self.configure_custom_endpoint(OpenAIConfig::new());
                Ok(Client::with_config(config))
            }
            (CredentialsKind::OwnOpenAiKey, key) => {
                let config =

View on GitHub (pinned to 58e5313667)