{"record":{"id":"9c957da8938d0b80","repo":"nautechsystems/nautilus_trader","slug":"cannot-convert-address-variant-to-poolid-bytes","errorCode":null,"errorMessage":"Cannot convert Address variant to PoolId bytes","messagePattern":"Cannot convert Address variant to PoolId bytes","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/pool_identifier.rs","lineNumber":212,"sourceCode":"            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) {\n            (Self::Address(a), Self::Address(b)) | (Self::PoolId(a), Self::PoolId(b)) => {\n                // Case-insensitive comparison","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/pool_identifier.rs#L194-L230","documentation":"Variant guard in PoolIdentifier::to_pool_id_bytes: the 32-byte pool ID only exists for the PoolId variant (V4 pools); calling it on an Address-variant identifier (V2/V3 pools) has no meaningful result and bails.","triggerScenarios":"Calling pool_identifier.to_pool_id_bytes() on a value built from a 42-char EVM address (e.g. a Uniswap V2/V3 pool address).","commonSituations":"Passing a V2/V3 pool address into a code path expecting a V4 pool ID; mixing pool types in subscription configuration.","solutions":["Ensure the identifier comes from a V4 pool with a 66-char pool ID before calling to_pool_id_bytes","Use to_address for V2/V3 pool identifiers","Match on the enum variant and branch the conversion accordingly"],"exampleFix":"// before\nlet bytes = v3_pool.to_pool_id_bytes()?;\n// after\nif let PoolIdentifier::Address(addr) = &v3_pool {\n    let bytes = addr.to_address()?;\n}","handlingStrategy":"type-guard","validationCode":"matches!(pid, PoolIdentifier::PoolId(_))","typeGuard":"fn is_pool_id_variant(pid: &PoolIdentifier) -> bool {\n    matches!(pid, PoolIdentifier::PoolId(_))\n}","tryCatchPattern":"match pid.to_pool_id_bytes() {\n    Ok(bytes) => use_pool_id(bytes),\n    Err(e) if e.to_string().contains(\"Address variant\") => handle_v2_v3_pool(pid),\n    Err(e) => return Err(e),\n}","preventionTips":["Only use to_pool_id_bytes on identifiers built from 66-char pool IDs","Keep V4 and V2/V3 pool handling in separate code paths"],"tags":["rust","defi","enum","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}