nautechsystems/nautilus_trader · error

SetFeeProtocol event data is too short

Error message

SetFeeProtocol event data is too short

What it means

In the Hypersync parsing path for PancakeSwap V3 `SetFeeProtocol` events, the log's `data` payload is length-checked against 4 words (4 * 32 = 128 bytes) before ABI decoding; if it is shorter, the parser bails with this message. The SetFeeProtocol event data is two 32-byte words plus padding, so a shorter payload means the log is corrupt, truncated, or was not actually a SetFeeProtocol event.

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/pancakeswap_v3/fee_protocol_update.rs:67

///
/// # Panics
///
/// Panics if the contract address is not set in the log.
pub fn parse_fee_protocol_update_event_hypersync(
    dex: SharedDex,
    log: &HypersyncLog,
) -> anyhow::Result<FeeProtocolUpdateEvent> {
    validate_event_signature_hash(
        "SetFeeProtocolEvent",
        FEE_PROTOCOL_UPDATE_EVENT_SIGNATURE_HASH,
        log,
    )?;

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

        if data_bytes.len() < 4 * 32 {
            anyhow::bail!("SetFeeProtocol event data is too short");
        }

        let decoded = match <SetFeeProtocolEventData as SolType>::abi_decode(data_bytes) {
            Ok(decoded) => decoded,
            Err(e) => anyhow::bail!("Failed to decode SetFeeProtocol 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(FeeProtocolUpdateEvent::new(
            dex,
            pool_identifier,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Filter the Hypersync query by the exact SetFeeProtocol topic0 signature so only genuine SetFeeProtocol logs reach the parser.
  2. Before parsing, check `log.data.as_ref().map(|d| d.len()).unwrap_or(0) >= 128` and skip logs that fail.
  3. Verify the target contract is a stock PancakeSwap V3 pool whose SetFeeProtocol ABI matches `SetFeeProtocolEventData` (2 params, non-indexed).
  4. Log the offending log's address/tx hash to identify the emitting contract and exclude it if it is a non-standard fork.

Example fix

// before
if let Some(data) = &log.data {
    let decoded = <SetFeeProtocolEventData as SolType>::abi_decode(data.as_ref())?;
// after
if let Some(data) = &log.data {
    if data.as_ref().len() < 4 * 32 {
        tracing::warn!("skipping short SetFeeProtocol log (len={})", data.as_ref().len());
        return Ok(None);
    }
    let decoded = <SetFeeProtocolEventData as SolType>::abi_decode(data.as_ref())?;
Defensive patterns

Strategy: validation

Validate before calling

// before calling parse_fee_protocol_update_event_hypersync
let data_len = log.data.as_ref().map(|d| d.as_ref().len()).unwrap_or(0);
if data_len < 128 {
    tracing::warn!("SetFeeProtocol log data too short: {data_len}");
    return Ok(None);
}

Type guard

fn is_valid_set_fee_protocol_log(log: &HyperSyncLog) -> bool {
    log.topic0.as_deref() == Some(SET_FEE_PROTOCOL_TOPIC)
        && log.data.as_ref().map(|d| d.as_ref().len()).unwrap_or(0) >= 128
}

Try / catch

match parse_fee_protocol_update_event_hypersync(dex, &log) {
    Ok(ev) => store(ev),
    Err(e) if e.to_string().contains("too short") => {
        tracing::warn!("skipping malformed SetFeeProtocol log");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `parse_fee_protocol_update_event_hypersync` with a Hypersync log whose `data` field contains fewer than 128 bytes — e.g. a mis-filtered log (wrong topic0 in the query), a zero-length/empty data field, or a truncated payload from the provider.

Common situations: A Hypersync query whose topic0 filter accidentally matches logs with a different data layout; logs from a forked/modified PancakeSwap V3 deployment with a different event signature; provider-side data truncation; running the parser against logs fetched without the data column populated correctly.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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