{"record":{"id":"fea54d86c0e2c267","repo":"nautechsystems/nautilus_trader","slug":"failed-to-decode-pool-id-hex-e","errorCode":null,"errorMessage":"Failed to decode pool ID hex: {e}","messagePattern":"Failed to decode pool ID hex: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/pool_identifier.rs","lineNumber":210,"sourceCode":"            Self::Address(s) => Address::parse_checksummed(s.as_str(), None)\n                .map_err(|e| anyhow::anyhow!(\"Failed to parse address: {e}\")),\n            Self::PoolId(_) => anyhow::bail!(\"Cannot convert PoolId variant to Address\"),\n        }\n    }\n\n    /// Converts to native bytes array (V4 pools only).\n    ///\n    /// Returns the 32-byte pool ID for use in V4-specific operations.\n    ///\n    /// # Errors\n    ///\n    /// Returns error if this is an Address variant or if hex decoding fails.\n    pub fn to_pool_id_bytes(&self) -> anyhow::Result<[u8; 32]> {\n        match self {\n            Self::PoolId(s) => {\n                let hex_str = s.strip_prefix(\"0x\").unwrap_or(s.as_str());\n                hex::decode_array::<32>(hex_str)\n                    .map_err(|e| anyhow::anyhow!(\"Failed to decode pool ID hex: {e}\"))\n            }\n            Self::Address(_) => anyhow::bail!(\"Cannot convert Address variant to PoolId bytes\"),\n        }\n    }\n}\n\n/// Validates that a string contains only valid hexadecimal characters after \"0x\" prefix.\nfn validate_hex_string(s: &str) -> anyhow::Result<()> {\n    let hex_part = &s[2..];\n    if !hex_part.chars().all(|c| c.is_ascii_hexdigit()) {\n        anyhow::bail!(\"Invalid hex characters in: {s}\");\n    }\n    Ok(())\n}\n\nimpl PartialEq for PoolIdentifier {\n    fn eq(&self, other: &Self) -> bool {\n        match (self, other) {","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/pool_identifier.rs#L192-L228","documentation":"`PoolIdentifier::to_pool_id_bytes` decodes the PoolId variant's hex string into a fixed `[u8; 32]`. It errors when called on the `Address` variant, or when the stored hex cannot be decoded into exactly 32 bytes.","triggerScenarios":"Calling `to_pool_id_bytes()` on a `PoolIdentifier::Address`, or on a PoolId whose hex is corrupt/wrong-length (should be prevented by construction, but possible if built through other paths).","commonSituations":"Code handling a heterogeneous collection of pool identifiers uniformly; hex values mutated or sourced from external feeds without validation.","solutions":["Match on the variant and only call `to_pool_id_bytes()` for `PoolIdentifier::PoolId`.","For Address variants use `to_address()` and convert explicitly if a 32-byte form is truly needed.","Re-derive the identifier via `from_pool_id_hex` to guarantee a valid 64-char hex before conversion."],"exampleFix":"// before\nlet bytes = identifier.to_pool_id_bytes()?;\n// after\nlet bytes = match &identifier {\n    PoolIdentifier::PoolId(_) => identifier.to_pool_id_bytes()?,\n    PoolIdentifier::Address(_) => bail!(\"expected PoolId variant\"),\n};","handlingStrategy":"type-guard","validationCode":"fn expect_pool_id(id: &PoolIdentifier) -> Option<&Ustr> {\n    match id { PoolIdentifier::PoolId(p) => Some(p), _ => None }\n}","typeGuard":"fn is_pool_id_variant(id: &PoolIdentifier) -> bool {\n    matches!(id, PoolIdentifier::PoolId(_))\n}","tryCatchPattern":"match identifier.to_pool_id_bytes() {\n    Ok(bytes) => bytes,\n    Err(e) if e.to_string().contains(\"Address\") => handle_address_variant(),\n    Err(e) => return Err(e),\n}","preventionTips":["Match on the variant before converting","Construct pool IDs only via from_pool_id_bytes/from_pool_id_hex so stored hex is guaranteed valid","Keep addresses and pool IDs in separate collections/types rather than one mixed list"],"tags":["defi","type-mismatch","variant","hex-decode"],"backgroundTag":"incompatible-source-type","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"}