{"record":{"id":"d5d04b7fb750470d","repo":"gitbutlerapp/gitbutler","slug":"no-openai-own-key-configured-add-this-through-the","errorCode":null,"errorMessage":"No OpenAI own key configured. Add this through the GitButler settings","messagePattern":"No OpenAI own key configured\\. Add this through the GitButler settings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-llm/src/openai.rs","lineNumber":92,"sourceCode":"            config\n        }\n    }\n\n    pub fn credentials_kind(&self) -> CredentialsKind {\n        self.credentials.0.clone()\n    }\n\n    fn gitbutler_proxied_creds() -> Result<(CredentialsKind, Sensitive<String>)> {\n        let creds = secret::retrieve(GITBUTLER_ACCESS_TOKEN_HANDLE, secret::Namespace::BuildKind)?\n            .ok_or(anyhow::anyhow!(\n                \"No GitButler token available. Log-in to use the GitButler OpenAI provider\"\n            ))?;\n        Ok((CredentialsKind::GitButlerProxied, creds))\n    }\n\n    fn openai_own_key_creds() -> Result<(CredentialsKind, Sensitive<String>)> {\n        let creds = secret::retrieve(AI_OPENAI_SECRET_HANDLE, secret::Namespace::Global)?.ok_or(\n            anyhow::anyhow!(\n                \"No OpenAI own key configured. Add this through the GitButler settings\"\n            ),\n        )?;\n        Ok((CredentialsKind::OwnOpenAiKey, creds))\n    }\n\n    fn openai_env_var_creds() -> Result<(CredentialsKind, Sensitive<String>)> {\n        let creds = Sensitive(\n            std::env::var_os(\"OPENAI_API_KEY\")\n                .ok_or(anyhow::anyhow!(\n                    \"Environment variable OPENAI_API_KEY is not set\"\n                ))?\n                .into_string()\n                .map_err(|_| anyhow::anyhow!(\"Invalid UTF-8 in OPENAI_API_KEY\"))?,\n        );\n        Ok((CredentialsKind::EnvVarOpenAiKey, creds))\n    }\n}","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-llm/src/openai.rs#L74-L110","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add an OpenAI API key in GitButler settings so it is stored under AI_OPENAI_SECRET_HANDLE.","Or log in to GitButler to use the proxied provider.","Or export OPENAI_API_KEY so the env-var rung of the chain succeeds."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"let has_own_key = secret::retrieve(AI_OPENAI_SECRET_HANDLE, secret::Namespace::Global).ok().flatten().is_some();\nif !has_own_key { /* fall back to proxied or env-var */ }","typeGuard":"fn has_own_openai_key() -> bool {\n    secret::retrieve(AI_OPENAI_SECRET_HANDLE, secret::Namespace::Global)\n        .ok()\n        .flatten()\n        .is_some()\n}","tryCatchPattern":"let provider = OpenAiProvider::with(Some(CredentialsKind::OwnOpenAiKey), model)\n    .or_else(|| OpenAiProvider::with(None, model));","preventionTips":["Configure the key through GitButler settings so it lands in the expected secret handle.","In library code, request credentials without a preferred kind to leverage fallbacks.","When automation only sets env vars, do not request OwnOpenAiKey explicitly."],"tags":["llm","openai","api-key","credentials","settings"],"backgroundTag":"missing-api-key","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T11:17:13.642Z"}