nautechsystems/nautilus_trader · error

Missing data in CollectProtocol event log

Error message

Missing data in CollectProtocol event log

What it means

Raised by parse_fee_protocol_collect_event_hypersync when the CollectProtocol log has no data field at all (log.data is None). The event requires amount0 and amount1 in the data section, so without data there is nothing to decode and the parser bails.

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/fee_protocol_collect.rs:101

                .expect("Contract address should be set in logs")
                .as_ref(),
        );
        let pool_identifier = PoolIdentifier::Address(Ustr::from(&pool_address.to_string()));

        Ok(FeeProtocolCollectEvent::new(
            dex,
            pool_identifier,
            extract_block_number(log)?,
            extract_transaction_hash(log)?,
            extract_transaction_index(log)?,
            extract_log_index(log)?,
            sender,
            recipient,
            decoded.amount0,
            decoded.amount1,
        ))
    } else {
        anyhow::bail!("Missing data in CollectProtocol event log");
    }
}

/// Parses a `CollectProtocol` event from an RPC log.
///
/// # Errors
///
/// Returns an error if the log parsing fails or if the event data is invalid.
pub fn parse_fee_protocol_collect_event_rpc(
    dex: SharedDex,
    log: &RpcLog,
) -> anyhow::Result<FeeProtocolCollectEvent> {
    rpc_log::validate_event_signature(
        log,
        FEE_PROTOCOL_COLLECT_EVENT_SIGNATURE_HASH,
        "CollectProtocol",
    )?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure log.data is Some with >= 64 bytes before calling the parser
  2. Filter by the exact CollectProtocol topic0 so only correct event shapes arrive
  3. Re-fetch the log from HyperSync if data is unexpectedly absent
  4. Return Ok(None)/skip for logs without data instead of treating them as errors

Example fix

// before
let event = parse_fee_protocol_collect_event_hypersync(&dex, &log)?;
// after
if log.data.is_none() {
    tracing::warn!("CollectProtocol log missing data, skipping");
    return Ok(None);
}
let event = parse_fee_protocol_collect_event_hypersync(&dex, &log)?;
Defensive patterns

Strategy: type-guard

Validate before calling

if log.data.is_none() {
    tracing::warn!("CollectProtocol log has no data, skipping");
    return Ok(None);
}
let event = parse_fee_protocol_collect_event_hypersync(&dex, &log)?;

Type guard

fn has_data(log: &Log) -> bool {
    log.data.as_deref().map_or(false, |d| d.len() >= 64)
}
// if !has_data(&log) { skip }

Try / catch

match parse_fee_protocol_collect_event_hypersync(&dex, &log) {
    Ok(event) => handle(event),
    Err(e) if e.to_string().contains("Missing data") => {
        tracing::warn!("CollectProtocol log without data, skipping");
        Ok(None)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A HyperSync log where data is None/null; accidentally passing an event with all parameters indexed (no data section); fixtures built without the data field.

Common situations: Provider responses omitting data for some logs; filtering with a too-broad topic0 catching fully-indexed variants; test helpers constructing minimal logs.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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