{"record":{"id":"3776862c21550077","repo":"gitbutlerapp/gitbutler","slug":"environment-variable-anthropic-api-key-is-not-set","errorCode":null,"errorMessage":"Environment variable ANTHROPIC_API_KEY is not set","messagePattern":"Environment variable ANTHROPIC_API_KEY is not set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-llm/src/anthropic.rs","lineNumber":155,"sourceCode":"        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 Anthropic provider\"\n            ))?;\n        Ok((CredentialsKind::GitButlerProxied, creds))\n    }\n\n    fn anthropic_own_key_creds() -> Result<(CredentialsKind, Sensitive<String>)> {\n        let creds = secret::retrieve(AI_ANTHROPIC_SECRET_HANDLE, secret::Namespace::Global)?\n            .ok_or(anyhow::anyhow!(\n                \"No Anthropic own key configured. Add this through the GitButler settings\"\n            ))?;\n        Ok((CredentialsKind::OwnAnthropicKey, creds))\n    }\n\n    fn anthropic_env_var_creds() -> Result<(CredentialsKind, Sensitive<String>)> {\n        let creds = Sensitive(\n            std::env::var_os(\"ANTHROPIC_API_KEY\")\n                .ok_or(anyhow::anyhow!(\n                    \"Environment variable ANTHROPIC_API_KEY is not set\"\n                ))?\n                .into_string()\n                .map_err(|_| anyhow::anyhow!(\"Invalid UTF-8 in ANTHROPIC_API_KEY\"))?,\n        );\n        Ok((CredentialsKind::EnvVarAnthropicKey, creds))\n    }\n}\n\nimpl LLMClient for AnthropicProvider {\n    fn model(&self) -> Option<String> {\n        self.model.clone()\n    }\n\n    fn tool_calling_loop_stream(\n        &self,\n        system_message: &str,\n        chat_messages: Vec<ChatMessage>,","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-llm/src/anthropic.rs#L137-L173","documentation":"Thrown by AnthropicProvider::anthropic_env_var_creds in crates/but-llm/src/anthropic.rs when std::env::var_os(\"ANTHROPIC_API_KEY\") returns None. This is the last rung of the credential fallback chain (proxied token -> own key -> env var), so hitting it means no Anthropic credential source is available at all.","triggerScenarios":"AnthropicProvider::with(Some(CredentialsKind::EnvVarAnthropicKey), _) without the variable exported; the full fallback chain reached with no login, no saved key, and no env var; the variable set only in the desktop app's environment but not in the shell running the CLI.","commonSituations":"Running but/CLI in a fresh shell, container, or CI where ANTHROPIC_API_KEY was never exported; setting the var in .zshrc but launching from an environment that does not source it; systemd/launchd services with a restricted environment.","solutions":["Export ANTHROPIC_API_KEY in the shell or service environment that runs the binary.","Or log in to GitButler / save an own key so earlier fallback rungs succeed.","For daemons/CI, inject the variable via the service's environment configuration rather than the interactive shell."],"exampleFix":"# before\n$ but ai ...\n# error: Environment variable ANTHROPIC_API_KEY is not set\n\n# after\n$ export ANTHROPIC_API_KEY=\"sk-ant-...\"\n$ but ai ...","handlingStrategy":"validation","validationCode":"// Rust: check before selecting the env-var provider\nlet key_present = std::env::var_os(\"ANTHROPIC_API_KEY\").is_some();\n\n// Shell (CI): guard the whole step\n// [ -n \"$ANTHROPIC_API_KEY\" ] || { echo \"ANTHROPIC_API_KEY missing\"; exit 1; }","typeGuard":"fn anthropic_env_key_available() -> bool {\n    std::env::var_os(\"ANTHROPIC_API_KEY\")\n        .map(|v| v.to_str().map(|s| !s.is_empty()).unwrap_or(false))\n        .unwrap_or(false)\n}","tryCatchPattern":"let provider = match AnthropicProvider::with(Some(CredentialsKind::EnvVarAnthropicKey), model) {\n    Some(p) => p,\n    None => AnthropicProvider::with(None, model).expect(\"no Anthropic credentials\"),\n};","preventionTips":["Export ANTHROPIC_API_KEY in the exact environment that runs the binary (shell, service unit, CI job).","Add a startup check that fails fast with a clear message when the variable is absent.","Prefer the settings-stored key for GUI-driven flows; reserve the env var for automation."],"tags":["llm","anthropic","environment-variables","credentials"],"backgroundTag":"missing-env-var","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}