nautechsystems/nautilus_trader · error

Burn event data is too short

Error message

Burn event data is too short

What it means

Raised by parse_burn_event_hypersync when the Burn event's data section contains fewer than 96 bytes (3 x 32). A Uniswap V3 Burn event encodes amount, txgBalance0 and txgBalance1 (amount0, amount1) as three 32-byte words in data. If the data is shorter the ABI layout cannot be honored, so the parser rejects the log rather than decoding garbage.

Solutions

  1. Confirm the topic0 filter targets exactly the Uniswap V3 Burn event signature so only genuine Burn logs reach the parser
  2. Pre-validate log.data length before calling the parser and skip/log logs with fewer than 96 data bytes
  3. Inspect the raw log (data hex length) for the failing transaction on a block explorer to see what event was actually emitted
  4. Fix the test fixture so the data hex string encodes three full 32-byte words (64+96 hex chars / 0x + 192 hex chars)

Example fix

// before
if let Some(data) = &log.data {
    let data_bytes = data.as_ref();
    if data_bytes.len() < 3 * 32 { anyhow::bail!("Burn event data is too short"); }
// after (caller-side)
if log.data.as_ref().map(|d| d.len()).unwrap_or(0) < 96 {
    tracing::warn!("skipping log with insufficient Burn event data");
    return Ok(None);
}
parse_burn_event_hypersync(log)?;
Defensive patterns

Strategy: validation

Validate before calling

fn burn_data_ok(log: &HyperSyncLog) -> bool {
    log.data.as_ref().map(|d| d.len() >= 96).unwrap_or(false)
}
// call parse_burn_event_hypersync only if burn_data_ok(&log)

Try / catch

match parse_burn_event_hypersync(&log) {
    Ok(ev) => handle(ev),
    Err(e) if e.to_string().contains("Burn event data is too short") => {
        tracing::warn!("short burn data; skipping log");
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling parse_burn_event_hypersync with a HyperSync log whose data field is missing, empty, or truncated to fewer than 96 bytes — e.g. a non-Burn event matched by a loose topic0 filter, or a fixture with partial data.

Common situations: Broad subscription filters capturing other events with 4 topics; malformed/truncated log payloads from a HyperSync response; test fixtures with hex data strings that are too short (e.g. only one 32-byte word); an empty string data field decoded to zero bytes.

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

Appendix: source

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

        }
        None => anyhow::bail!("Missing tickLower in topic2 when parsing burn event"),
    };

    // Extract int24 tickUpper from topic3 (stored as a 32-byte padded value)
    let tick_upper = match log.topics.get(3).and_then(|t| t.as_ref()) {
        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,

View on GitHub (pinned to 18893faf8b)