{"record":{"id":"b935d1d45353302e","repo":"Hmbown/CodeWhale","slug":"refusing-to-save-an-empty-api-key","errorCode":null,"errorMessage":"Refusing to save an empty API key.","messagePattern":"Refusing to save an empty API key\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":10314,"sourceCode":"/// removed. When the secret-store write fails (OS permission denied, corrupt\n/// or read-only file backend, etc.), the save fails loudly rather than writing\n/// the key to plaintext `config.toml`.\n///\n/// Under `cfg(test)` the secret-store path is enabled only when the test sets\n/// both an isolated `CODEWHALE_HOME` and an explicit backend, preventing unit\n/// tests from touching the developer's real credential store.\npub fn save_api_key(api_key: &str) -> Result<SavedCredential> {\n    save_root_api_key_for_secret_slot(api_key, \"deepseek\", true)\n}\n\nfn save_root_api_key_for_secret_slot(\n    api_key: &str,\n    secret_slot: &str,\n    clear_deepseek_provider_slot: bool,\n) -> Result<SavedCredential> {\n    let trimmed = api_key.trim();\n    if trimmed.is_empty() {\n        anyhow::bail!(\"Refusing to save an empty API key.\");\n    }\n\n    let path = credential_config_path().context(\"Failed to resolve config path for API key.\")?;\n\n    if let Some(secrets) = credential_secret_store() {\n        let prior_secret = secrets.get(secret_slot);\n        match prior_secret.as_ref() {\n            Ok(prior) => match secrets.set(secret_slot, trimmed) {\n                Ok(()) => {\n                    if let Err(error) = save_root_api_key_metadata_without_plaintext(\n                        &path,\n                        clear_deepseek_provider_slot,\n                    ) {\n                        let current = secrets.get(secret_slot).map_err(|rollback| {\n                        anyhow::anyhow!(\n                            \"{error}; additionally could not verify secret-store rollback for {secret_slot}: {rollback}\"\n                        )\n                    })?;","sourceCodeStart":10296,"sourceCodeEnd":10332,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/config.rs#L10296-L10332","documentation":"Error \"Refusing to save an empty API key.\" thrown in Hmbown/CodeWhale.","triggerScenarios":"Thrown at crates/tui/src/config.rs:10314 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}