{"record":{"id":"56a6680ace525c47","repo":"gitbutlerapp/gitbutler","slug":"no-gitbutler-token-available-log-in-to-use-the-gi-56a668","errorCode":null,"errorMessage":"No GitButler token available. Log-in to use the GitButler OpenAI provider","messagePattern":"No GitButler token available\\. Log-in to use the GitButler OpenAI provider","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-llm/src/openai.rs","lineNumber":84,"sourceCode":"        }\n    }\n\n    /// Configure a custom endpoint if set in the provider, if any.\n    fn configure_custom_endpoint(&self, config: OpenAIConfig) -> OpenAIConfig {\n        if let Some(custom_endpont) = &self.custom_endpoint {\n            config.with_api_base(custom_endpont)\n        } else {\n            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!(","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-llm/src/openai.rs#L66-L102","documentation":"OpenAI counterpart of the Anthropic token error, thrown by OpenAiProvider::gitbutler_proxied_creds in crates/but-llm/src/openai.rs when secret::retrieve(GITBUTLER_ACCESS_TOKEN_HANDLE, Namespace::BuildKind) returns None. The GitButler-proxied OpenAI provider requires the logged-in user's access token to route requests through GitButler's proxy.","triggerScenarios":"Constructing OpenAiProvider with preferred_creds = Some(CredentialsKind::GitButlerProxied) while not logged in; the no-preference fallback chain reaching proxied creds first when no other OpenAI credential exists.","commonSituations":"CLI/TUI usage without a prior desktop-app login; token cleared by logout or keychain reset; CI runners with no GitButler session.","solutions":["Log in via the GitButler desktop app to populate the access token secret.","Or add an OpenAI API key in GitButler settings (OwnOpenAiKey path).","Or export OPENAI_API_KEY for the env-var credential path.","Pass preferred_creds = None to let the provider fall back across all three sources."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"let has_token = secret::retrieve(GITBUTLER_ACCESS_TOKEN_HANDLE, secret::Namespace::BuildKind).ok().flatten().is_some();\nif !has_token { /* choose own-key or env-var credentials */ }","typeGuard":"fn can_use_proxied_openai() -> bool {\n    secret::retrieve(GITBUTLER_ACCESS_TOKEN_HANDLE, secret::Namespace::BuildKind)\n        .ok()\n        .flatten()\n        .is_some()\n}","tryCatchPattern":"let provider = match OpenAiProvider::with(Some(CredentialsKind::GitButlerProxied), model) {\n    Some(p) => p,\n    None => OpenAiProvider::with(None, model).expect(\"no OpenAI credentials\"),\n};","preventionTips":["Log in through the desktop app before using proxied providers from the CLI.","Use preferred_creds = None in library call sites to enable the fallback chain.","Detect logout/secret-store resets in long-lived processes and re-resolve credentials."],"tags":["llm","openai","credentials","authentication","secret-store"],"backgroundTag":"missing-auth-token","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T11:17:13.642Z"}