{"record":{"id":"439ef1968b6d67c2","repo":"gleam-lang/gleam","slug":"oauth-credentials-toml-encoding","errorCode":null,"errorMessage":"OAuth credentials TOML encoding","messagePattern":"OAuth credentials TOML encoding","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-cli/src/hex/auth.rs","lineNumber":139,"sourceCode":"        let encrypted_refresh_token =\n            encryption::encrypt_with_passphrase(tokens.refresh_token.as_bytes(), &local_password)\n                .map_err(|error| Error::FailedToEncryptLocalHexApiKey {\n                detail: error.to_string(),\n            })?;\n\n        let credentials = StoredOAuthCredentials {\n            hexpm: StoredOAuthRepoCredentials {\n                api: self.hex_config.api_base.clone(),\n                repository: self.hex_config.repository_base.clone(),\n                refresh_token: encrypted_refresh_token,\n                refresh_token_hash: {\n                    let mut hasher = sha2::Sha256::new();\n                    hasher.update(tokens.refresh_token.as_bytes());\n                    base16::encode_lower(&hasher.finalize())\n                },\n            },\n        };\n        let toml = toml::to_string(&credentials).expect(\"OAuth credentials TOML encoding\");\n        crate::fs::write(&path, &toml)?;\n        Ok(())\n    }\n\n    /// Create a new local password.\n    ///\n    /// The password must be long enough.\n    ///\n    /// The old password will be discarded, and the new one will be both\n    /// returned and stored in `self.local_password`\n    ///\n    fn ask_for_new_local_password(&mut self) -> Result<()> {\n        let required_length = 8;\n        self.local_password = None;\n        println!(\n            \"Please enter a new unique password, at least {required_length} characters long.\nIt will be used to locally encrypt your Hex API tokens.\n\"","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/gleam-lang/gleam/blob/15b07c783065c92bb016b1b74ed0995a5259850f/compiler-cli/src/hex/auth.rs#L121-L157","documentation":"Panic from `toml::to_string(&credentials).expect(\"OAuth credentials TOML encoding\")` in encrypt_and_store_oauth_refresh_token in compiler-cli/src/hex/auth.rs. Serializing the Hex credentials struct to TOML failed — practically only possible if the struct contains types the toml serializer cannot represent (e.g. None-bearing fields where the schema expects strings, or map types TOML can't express). The stored OAuth credentials file therefore cannot be written.","triggerScenarios":"Completing the OAuth device flow (create_and_store_new_credentials_via_oauth) or refreshing stored tokens (read_and_decrypt_and_refresh_stored_tokens) when the credentials struct shape can't be represented in TOML — e.g. after a struct field type change in HexAuthentication's credentials model.","commonSituations":"A refactor changes a credentials field to a nested map/Option layout the toml crate rejects; upgrading the toml crate introduces stricter serializer rules.","solutions":["Inspect the credentials struct and ensure all fields are TOML-compatible (strings, plain structs, no nested maps under non-string keys, no unexpected None).","Replace the expect with proper error propagation so the user sees a message instead of a panic.","Update the serde attributes (skip_serializing_if = \"Option::is_none\") on fields that may be absent.","Pin or upgrade the toml crate deliberately after verifying the struct still serializes; add a round-trip unit test."],"exampleFix":"// before\nlet toml = toml::to_string(&credentials).expect(\"OAuth credentials TOML encoding\");\n// after\nlet toml = toml::to_string(&credentials)\n    .map_err(|e| anyhow::anyhow!(\"Failed to encode OAuth credentials as TOML: {e}\"))?;","handlingStrategy":"validation","validationCode":"// Round-trip check before storing:\nif toml::to_string(&credentials).is_err() { eprintln!(\"credentials not TOML-serializable\"); }","typeGuard":"fn toml_serializable<T: serde::Serialize>(v: &T) -> bool { toml::to_string(v).is_ok() }","tryCatchPattern":"match toml::to_string(&credentials) { Ok(t) => crate::fs::write(&path, &t)?, Err(e) => return Err(anyhow::anyhow!(\"TOML encoding failed: {e}\")) }","preventionTips":["Keep credentials structs limited to TOML-friendly field types.","Add round-trip (serialize->deserialize) unit tests for credential storage.","Annotate optional fields with skip_serializing_if."],"tags":["rust","toml","serialization","oauth","panic"],"backgroundTag":"json-marshal-failed","analyzedSha":"15b07c783065c92bb016b1b74ed0995a5259850f","analyzedAt":"2026-09-14T11:14:59.388Z","contentChangedAt":"2026-09-14T11:14:59.388Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}