nautechsystems/nautilus_trader · error

Failed to decode burn event data: {e}

Error message

Failed to decode burn event data: {e}

What it means

Raised by parse_burn_event_hypersync when alloy's ABI decoder fails to decode the Burn event data as BurnEventData, even though the 96-byte length check passed. The underlying alloy error is interpolated into the message. This means the bytes are long enough but do not match the Burn event ABI layout (types/values mismatch).

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/burn.rs:89

        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 burn 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!("Burn event data is too short");
        }

        // Decode the data using the BurnEventData struct
        let decoded = match <BurnEventData as SolType>::abi_decode(data_bytes) {
            Ok(decoded) => decoded,
            Err(e) => anyhow::bail!("Failed to decode burn 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(BurnEvent::new(
            dex,
            pool_identifier,
            extract_block_number(log)?,
            extract_transaction_hash(log)?,
            extract_transaction_index(log)?,
            extract_log_index(log)?,
            owner,
            tick_lower,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log the full {e} from the bail plus the data hex to identify the exact decoding failure (offset/length mismatch, invalid value)
  2. Verify the topic0 filter matches the exact Burn event signature hash so only Burn-event data reaches the decoder
  3. Check the BurnEventData type in the contract bindings matches the pool contract version actually emitting the log (regenerate bindings with alloy if the ABI changed)
  4. Inspect the raw log's data field against the expected Burn layout (uint128 amount, uint256 amount0, uint256 amount1) on a block explorer

Example fix

// before
Err(e) => anyhow::bail!("Failed to decode burn event data: {e}"),
// after (caller-side diagnostic + skip)
match parse_burn_event_hypersync(log) {
    Ok(ev) => { /* use ev */ }
    Err(e) if e.to_string().contains("Failed to decode burn event data") => {
        tracing::warn!(data = ?log.data, "non-Burn data layout; skipping: {e:#}");
        return Ok(None);
    }
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: try-catch

Validate before calling

fn plausible_burn_data(data: &[u8]) -> bool {
    data.len() == 96 && data.iter().all(|b| true) // length exact; deep check via re-encoding
}
// optionally re-encode the decoded struct and compare bytes to detect layout drift

Try / catch

match parse_burn_event_hypersync(&log) {
    Ok(ev) => handle(ev),
    Err(e) if e.to_string().contains("Failed to decode burn event data") => {
        tracing::warn!(e = %e, data = ?log.data, "ABI decode failed; quarantining log");
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling parse_burn_event_hypersync with data whose 96+ bytes do not decode as BurnEventData — e.g. data from a different event type with a similar shape, byte-swapped or truncated-but-padded data, or data encoded for an older/other contract version.

Common situations: Wrong topic filter capturing another event with 4 topics and >=96 data bytes; data hex string decoded with wrong endianness or with non-hex characters stripped in fixtures; a contract upgrade changing the data layout; corrupted payloads from a third-party indexer.

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/afce8cc09815fc1d. Report an issue: GitHub.