{"record":{"id":"3c7a2953aa254b85","repo":"nautechsystems/nautilus_trader","slug":"api-key-is-valid-utf-8","errorCode":null,"errorMessage":"API key is valid UTF-8","messagePattern":"API key is valid UTF-8","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/adapters/databento/src/common.rs","lineNumber":96,"sourceCode":"    /// Creates a new [`Credential`] instance from the API key.\n    #[must_use]\n    pub fn new(api_key: impl Into<String>) -> Self {\n        let api_key_bytes = api_key.into().into_bytes();\n\n        Self {\n            api_key: api_key_bytes.into_boxed_slice(),\n        }\n    }\n\n    /// Returns the API key associated with this credential.\n    ///\n    /// # Panics\n    ///\n    /// This method should never panic as the API key is always valid UTF-8,\n    /// having been created from a String.\n    #[must_use]\n    pub fn api_key(&self) -> &str {\n        std::str::from_utf8(&self.api_key).expect(\"API key is valid UTF-8\")\n    }\n\n    /// Returns a masked version of the API key for logging purposes.\n    ///\n    /// Shows first 4 and last 4 characters with ellipsis in between.\n    /// For keys shorter than 8 characters, shows asterisks only.\n    #[must_use]\n    pub fn api_key_masked(&self) -> String {\n        nautilus_core::string::secret::mask_api_key(self.api_key())\n    }\n}\n\n/// # Errors\n///\n/// Returns an error if converting `start` or `end` to `OffsetDateTime` fails.\npub fn get_date_time_range(start: UnixNanos, end: UnixNanos) -> anyhow::Result<DateTimeRange> {\n    Ok(DateTimeRange::from((\n        OffsetDateTime::from_unix_timestamp_nanos(i128::from(start.as_u64()))?,","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/databento/src/common.rs#L78-L114","documentation":"DatabentoApiKey::api_key() returns the key as &str; the key is stored as raw bytes and this accessor converts with str::from_utf8, expecting success. The invariant holds because the key is only ever constructed from a String (valid UTF-8), so the panic indicates the byte storage was corrupted or built through a non-validating path.","triggerScenarios":"In practice unreachable when using the documented constructor from String; could only fire if the api_key bytes were written via unsafe code or loaded from a non-UTF-8 source without validation.","commonSituations":"Custom deserialization (e.g. reading the key from a file or env as raw bytes) that bypasses the String-based constructor is the realistic way this invariant would be broken.","solutions":["Construct DatabentoApiKey only via its String/&str-based API so UTF-8 is validated at the boundary.","If loading from raw bytes, validate with String::from_utf8 first and surface a proper error.","Report a bug if this fires with stock constructors — it indicates memory corruption or an unsafe path."],"exampleFix":"// before\nlet key = DatabentoApiKey::from_raw_bytes(untrusted); // may violate UTF-8 invariant\n// after\nlet s = String::from_utf8(untrusted).map_err(|e| Error::InvalidApiKey(e))?;\nlet key = DatabentoApiKey::new(s);","handlingStrategy":"validation","validationCode":"let key_str = String::from_utf8(raw_key_bytes)\n    .map_err(|e| anyhow!(\"Databento API key is not UTF-8: {e}\"))?;\nlet key = DatabentoApiKey::new(key_str);","typeGuard":"fn is_valid_api_key(bytes: &[u8]) -> bool { std::str::from_utf8(bytes).is_ok() }","tryCatchPattern":null,"preventionTips":["Build the key only from String/&str sources (env vars, config strings).","Validate UTF-8 at the boundary when loading raw bytes from files or network.","Never write into the key's internal byte storage directly."],"tags":["rust","utf-8","panic","databento","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}