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 OpenAiProvider::openai_env_var_creds in crates/but-llm/src/openai.rs when std::env::var_os("OPENAI_API_KEY") returns None. It is the final rung of the OpenAI credential fallback (proxied token -> own key -> env var), so seeing it means no OpenAI credential source is configured anywhere.

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 caf1f223d3)

Solutions

  1. Export OPENAI_API_KEY in the environment that runs the binary.
  2. Or configure an own key in settings / log in to GitButler so earlier rungs succeed.
  3. For services, add the variable to the unit's Environment= or the runner's secret configuration.

Example fix

# before
$ but ai ...
# error: Environment variable OPENAI_API_KEY is not set

# after
$ export OPENAI_API_KEY="sk-..."
$ but ai ...
Defensive patterns

Strategy: validation

Validate before calling

// Rust: check before selecting the env-var provider
let key_present = std::env::var_os("OPENAI_API_KEY").is_some();

// Shell (CI): guard the step
// [ -n "$OPENAI_API_KEY" ] || { echo "OPENAI_API_KEY missing"; exit 1; }

Type guard

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

Try / catch

let provider = match OpenAiProvider::with(Some(CredentialsKind::EnvVarOpenAiKey), model) {
    Some(p) => p,
    None => OpenAiProvider::with(None, model).expect("no OpenAI credentials"),
};

Prevention

When it happens

Trigger: Requesting CredentialsKind::EnvVarOpenAiKey explicitly without the variable set; the full fallback chain exhausted with no login, no saved key, and no env var; the variable existing only in a different shell/service context.

Common situations: Fresh shells, containers, or CI jobs where OPENAI_API_KEY was never exported; the variable set in the desktop app's launch environment but not the CLI's; service units with a minimal environment block.

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@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/a71dec370e43fe00. Report an issue: GitHub.