gitbutlerapp/gitbutler · error

No OpenAI own key configured. Add this through the…

Error message

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

What it means

Thrown by `openai_own_key_creds` when `secret::retrieve(AI_OPENAI_SECRET_HANDLE, Namespace::Global)` returns Ok(None) — the OS secret store holds no stored OpenAI key under GitButler's handle. This credential kind is only used when the user explicitly configured their own OpenAI key, so an absent entry means the stored key was never created or has since been removed.

Solutions

  1. Open GitButler settings and add/save your OpenAI API key
  2. Alternatively export OPENAI_API_KEY so the env-var credential path can be used
  3. Or switch back to the GitButler-proxied provider after logging in
  4. Check the OS keychain (Keychain Access / GNOME Keyring / Windows Credential Manager) for an accidentally deleted GitButler entry

Example fix

// before: settings.json has mode "own" but no key stored
// after: save key via settings UI, or
$ export OPENAI_API_KEY=sk-proj-...
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = result {
    if e.to_string().contains("No OpenAI own key") {
        eprintln!("Add your OpenAI key in GitButler settings or export OPENAI_API_KEY");
    }
}

Prevention

When it happens

Trigger: Credential resolution selects the own-key path (`openai_own_key_creds`) but no key was ever saved under AI_OPENAI_SECRET_HANDLE — e.g. settings entry cleared, keychain entry deleted externally, or a fresh profile/machine without re-entering the key.

Common situations: User toggled to "use my own OpenAI key" mode without saving the key; OS keychain wiped or reset; migrating machines without re-entering secrets; a settings sync that changed the mode but not the secret.

Related errors


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

Appendix: 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 58e5313667)