nautechsystems/nautilus_trader · error

Failed to decode collect event data: {e}

Error message

Failed to decode collect event data: {e}

What it means

Raised when ABI-decoding the 96+ byte Collect event data with CollectEventData::abi_decode fails; the underlying alloy-sol error is embedded in the message. The length pre-check passed but the byte layout does not conform to the expected (uint256, uint256, uint256) tuple.

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/collect.rs:92

        Some(topic) => {
            let tick_upper_bytes: [u8; 32] = topic.as_ref().try_into()?;
            i32::from_be_bytes(tick_upper_bytes[28..32].try_into()?)
        }
        None => anyhow::bail!("Missing tickUpper in topic3 when parsing collect event"),
    };

    if let Some(data) = &log.data {
        let data_bytes = data.as_ref();

        // Validate if data contains 3 parameters of 32 bytes each
        if data_bytes.len() < 3 * 32 {
            anyhow::bail!("Collect event data is too short");
        }

        // Decode the data using the CollectEventData struct
        let decoded = match <CollectEventData as SolType>::abi_decode(data_bytes) {
            Ok(decoded) => decoded,
            Err(e) => anyhow::bail!("Failed to decode collect event data: {e}"),
        };

        let pool_address = Address::from_slice(
            log.address
                .clone()
                .expect("Contract address should be set in logs")
                .as_ref(),
        );
        let pool_identifier = PoolIdentifier::Address(Ustr::from(&pool_address.to_string()));
        Ok(CollectEvent::new(
            dex,
            pool_identifier,
            extract_block_number(log)?,
            extract_transaction_hash(log)?,
            extract_transaction_index(log)?,
            extract_log_index(log)?,
            owner,
            decoded.recipient,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Compare the embedded error against the expected CollectEventData types to find the mismatch
  2. Verify topic0 equals the canonical Collect(event signature for V3 pools
  3. Re-fetch logs with the correct ABI/event filter from HyperSync
  4. Print data_bytes hex and decode manually (e.g. cast abi-decode) to diagnose

Example fix

// before
let decoded = <CollectEventData as SolType>::abi_decode(data_bytes)?;
// after
let expected_topic0 = <Collect as SolEvent>::SIGNATURE_HASH;
anyhow::ensure!(log.topics[0].as_ref().map(|t| **t) == Some(expected_topic0), "not a Collect event");
let decoded = <CollectEventData as SolType>::abi_decode(data_bytes)?;
Defensive patterns

Strategy: try-catch

Validate before calling

fn topic0_matches(log: &Log, sig: [u8; 32]) -> bool {
    log.topics.first().and_then(|t| t.as_deref()) == Some(&sig)
}
// ensure topic0_matches(&log, <Collect as SolEvent>::SIGNATURE_HASH)

Type guard

fn is_canonical_collect(log: &Log) -> bool {
    log.topics.first().and_then(|t| t.as_deref()) == Some(&COLLECT_TOPIC0)
}

Try / catch

let decoded = <CollectEventData as SolType>::abi_decode(data_bytes)
    .with_context(|| format!("collect decode failed, topic0={:?}, data_len={}", log.topics.first(), data_bytes.len()))?;
// surface topic0+hex data in logs for diagnosis

Prevention

When it happens

Trigger: Data from a different event signature decoded as Collect data; stray extra/offset encoding; non-standard contracts emitting a same-named event with different parameter types.

Common situations: Forked or modified Uniswap V3 deployments with altered Collect events; decoding logs fetched with a stale ABI; mixing big-endian/hex formatting bugs when constructing test data.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/bc06f493cfb19c88. Report an issue: GitHub.