nautechsystems/nautilus_trader · error · anyhow::Error
Cannot convert PoolId variant to Address
Error message
Cannot convert PoolId variant to Address
What it means
PoolIdentifier is an enum of Address (20-byte) and PoolId (32-byte V4) variants; to_address only makes sense for the Address variant. Calling it on a PoolId variant bails with this error because a 32-byte pool ID cannot be represented as a 20-byte Address.
Source
Thrown at crates/model/src/defi/pool_identifier.rs:194
/// Returns true if this is a `PoolId` variant (V4 pools).
#[must_use]
pub fn is_pool_id(&self) -> bool {
matches!(self, Self::PoolId(_))
}
/// Converts to native Address type (V2/V3 pools only).
///
/// Returns the underlying Address for use with alloy/ethers operations.
///
/// # Errors
///
/// Returns error if this is a `PoolId` variant or if parsing fails.
pub fn to_address(&self) -> anyhow::Result<Address> {
match self {
Self::Address(s) => Address::parse_checksummed(s.as_str(), None)
.map_err(|e| anyhow::anyhow!("Failed to parse address: {e}")),
Self::PoolId(_) => anyhow::bail!("Cannot convert PoolId variant to Address"),
}
}
/// Converts to native bytes array (V4 pools only).
///
/// Returns the 32-byte pool ID for use in V4-specific operations.
///
/// # Errors
///
/// Returns error if this is an Address variant or if hex decoding fails.
pub fn to_pool_id_bytes(&self) -> anyhow::Result<[u8; 32]> {
match self {
Self::PoolId(s) => {
let hex_str = s.strip_prefix("0x").unwrap_or(s.as_str());
hex::decode_array::<32>(hex_str)
.map_err(|e| anyhow::anyhow!("Failed to decode pool ID hex: {e}"))
}
Self::Address(_) => anyhow::bail!("Cannot convert Address variant to PoolId bytes"),View on GitHub (pinned to 18893faf8b)
Solutions
- Match on the PoolIdentifier enum and handle the PoolId variant separately before calling to_address
- Use to_pool_id_bytes for V4 pool identifiers instead
- Check the variant with matches! or an is-style helper before conversion
Example fix
// before
let addr = pool_id.to_address()?;
// after
let addr = match &pool_id {
PoolIdentifier::Address(_) => pool_id.to_address()?,
PoolIdentifier::PoolId(_) => anyhow::bail!("V4 pool: use to_pool_id_bytes()"),
}; Defensive patterns
Strategy: type-guard
Validate before calling
matches!(pid, PoolIdentifier::Address(_))
Type guard
fn is_address_variant(pid: &PoolIdentifier) -> bool {
matches!(pid, PoolIdentifier::Address(_))
} Try / catch
match pid.to_address() {
Ok(a) => use_address(a),
Err(e) if e.to_string().contains("PoolId variant") => handle_v4_pool(pid),
Err(e) => return Err(e),
} Prevention
- Track whether a pool is V4 (PoolId) or V2/V3 (Address) in your own types
- Branch on the enum variant before any conversion
When it happens
Trigger: Calling pool_identifier.to_address() on a value constructed via new_checked with a 66-char pool ID or from_pool_id_hex.
Common situations: Generic code that assumes all pool identifiers are addresses; subscribing to Uniswap V4 pools (which use pool IDs) and then calling address-only APIs.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot convert Address variant to PoolId bytes
- Expected Custom data variant
- Actor type mismatch for '{id}': expected {expected_type:?},
- Invalid NodeState value
- Native currency not specified for chain {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/5f3b8e6086d7ba54.
Report an issue: GitHub.