gitbutlerapp/gitbutler · error

No OpenAI own key configured. Add this through the GitButler

Error message

No OpenAI own key configured. Add this through the GitButler settings

What it means

Thrown by OpenAiProvider::openai_own_key_creds in crates/but-llm/src/openai.rs when secret::retrieve(AI_OPENAI_SECRET_HANDLE, Namespace::Global) returns None — no user-supplied OpenAI API key is saved in the secret store. Reached when OwnOpenAiKey is requested explicitly or when the fallback chain arrives here without a GitButler token.

Source

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

            config
        }
    }

    pub fn credentials_kind(&self) -> CredentialsKind {
        self.credentials.0.clone()
    }

    fn gitbutler_proxied_creds() -> Result<(CredentialsKind, Sensitive<String>)> {
        let creds = secret::retrieve(GITBUTLER_ACCESS_TOKEN_HANDLE, secret::Namespace::BuildKind)?
            .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))
    }
}

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Add an OpenAI API key in GitButler settings so it is stored under AI_OPENAI_SECRET_HANDLE.
  2. Or log in to GitButler to use the proxied provider.
  3. Or export OPENAI_API_KEY so the env-var rung of the chain succeeds.
Defensive patterns

Strategy: fallback

Validate before calling

let has_own_key = secret::retrieve(AI_OPENAI_SECRET_HANDLE, secret::Namespace::Global).ok().flatten().is_some();
if !has_own_key { /* fall back to proxied or env-var */ }

Type guard

fn has_own_openai_key() -> bool {
    secret::retrieve(AI_OPENAI_SECRET_HANDLE, secret::Namespace::Global)
        .ok()
        .flatten()
        .is_some()
}

Try / catch

let provider = OpenAiProvider::with(Some(CredentialsKind::OwnOpenAiKey), model)
    .or_else(|| OpenAiProvider::with(None, model));

Prevention

When it happens

Trigger: OpenAiProvider::with(Some(CredentialsKind::OwnOpenAiKey), ...) before any key was saved; fallback chain reaching this function for a user with no login and no OPENAI_API_KEY.

Common situations: Fresh setups where the settings UI was never used; keychain entry deleted or app data reset; automation that only configures env vars, not the settings store.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/d5d04b7fb750470d. Report an issue: GitHub.