{"record":{"id":"556753d225dc233c","repo":"gitbutlerapp/gitbutler","slug":"invalid-utf-8-in-openai-api-key","errorCode":null,"errorMessage":"Invalid UTF-8 in OPENAI_API_KEY","messagePattern":"Invalid UTF-8 in OPENAI_API_KEY","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-llm/src/openai.rs","lineNumber":106,"sourceCode":"    }\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}\n\nimpl OpenAIClientProvider for OpenAiProvider {\n    fn client(&self) -> Result<Client<OpenAIConfig>> {\n        match &self.credentials {\n            (CredentialsKind::EnvVarOpenAiKey, _) => {\n                let config = self.configure_custom_endpoint(OpenAIConfig::new());\n                Ok(Client::with_config(config))\n            }\n            (CredentialsKind::OwnOpenAiKey, key) => {\n                let config =\n                    self.configure_custom_endpoint(OpenAIConfig::new().with_api_key(key.0.clone()));\n                Ok(Client::with_config(config))\n            }\n","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-llm/src/openai.rs#L88-L124","documentation":"Thrown by `openai_env_var_creds` when `OPENAI_API_KEY` is set but not valid UTF-8. `OsString::into_string()` fails for non-UTF-8 byte sequences and the function maps that failure to this error, refusing to use a malformed credential.","triggerScenarios":"`std::env::var_os(\"OPENAI_API_KEY\")` succeeds but `.into_string()` errors because the value contains invalid UTF-8 bytes — corrupted export, wrong-encoding script, or binary paste into a dotfile.","commonSituations":"Pasting keys from editors/terminals that mangle encoding; locale misconfiguration (non-UTF-8 locale writing the var); provisioning scripts using binary tools without text mode.","solutions":["Re-export with a clean UTF-8 value from the OpenAI console","Inspect bytes (echo -n \"$OPENAI_API_KEY\" | xxd) and strip non-ASCII characters","Fix the script/profile writing the variable to write UTF-8 text","Store the key via GitButler settings to bypass the env var"],"exampleFix":"// before (invalid byte)\nexport OPENAI_API_KEY=$'sk-\\xff...'\n\n// after\nexport OPENAI_API_KEY=sk-proj-clean-key","handlingStrategy":"validation","validationCode":"fn openai_key_is_utf8() -> bool {\n    std::env::var_os(\"OPENAI_API_KEY\")\n        .map(|v| v.into_string().is_ok())\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = result {\n    if e.to_string().contains(\"Invalid UTF-8 in OPENAI_API_KEY\") {\n        eprintln!(\"OPENAI_API_KEY has invalid bytes; re-copy as plain UTF-8\");\n    }\n}","preventionTips":["Paste keys from plain-text sources only","Save provisioning scripts with UTF-8 encoding","Run with a UTF-8 locale (LANG=C.UTF-8)","Validate the value with a quick `[[ \"$OPENAI_API_KEY\" =~ ^[[:print:]]+$ ]]` check"],"tags":["environment","encoding","utf-8","openai"],"backgroundTag":"invalid-env-var-value","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}