nautechsystems/nautilus_trader · error

Swap event data is too short

Error message

Swap event data is too short

What it means

parse_swap_event_hypersync decodes a PancakeSwap V3 Swap log whose data section must carry 7 ABI words (Uniswap V3's 5 fields plus two appended protocolFees words). Before decoding, the function checks `data_bytes.len() < 7 * 32` and bails with 'Swap event data is too short' if the payload cannot hold all 7 words. This guards the ABI decoder and surfaces a common case: a log with a Uniswap V3-style (5-word) data payload being fed to the PancakeSwap parser.

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/pancakeswap_v3/swap.rs:71

///
/// # Errors
///
/// Returns an error if the log parsing fails or if the event data is invalid.
///
/// # Panics
///
/// Panics if the contract address is not set in the log.
pub fn parse_swap_event_hypersync(dex: SharedDex, log: &HypersyncLog) -> anyhow::Result<SwapEvent> {
    validate_event_signature_hash("SwapEvent", SWAP_EVENT_SIGNATURE_HASH, log)?;

    let sender = extract_address_from_topic(log, 1, "sender")?;
    let recipient = extract_address_from_topic(log, 2, "recipient")?;

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

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

        let decoded = match <SwapEventData as SolType>::abi_decode(data_bytes) {
            Ok(decoded) => decoded,
            Err(e) => anyhow::bail!("Failed to decode swap 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(SwapEvent::new(
            dex,
            pool_identifier,
            extract_block_number(log)?,
            extract_transaction_hash(log)?,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the log is actually a PancakeSwap V3 Swap event: its topic0 must be 0x19b47279256b2a23a1665c810c8d55a1758940ee09377d4f8d26497a3577dc83 and data must be 0x + 448 hex chars (7 words); route Uniswap V3 topic0 (0xc42079f9...) to the Uniswap V3 parser instead
  2. Check the HyperSync query/response for truncation — re-fetch the log and confirm the full data field is returned
  3. Validate `log.data` length in your ingestion pipeline before calling parse_swap_event_hypersync and skip or quarantine logs shorter than 224 bytes
  4. If building fixtures/tests, base them on a real PancakeSwap V3 Swap log (7 data words) rather than a Uniswap V3 one

Example fix

// before: feeding a Uniswap V3 (5-word) data payload to the PancakeSwap parser
let log: HypersyncLog = serde_json::from_str(uniswap_style_log)?;
let event = parse_swap_event_hypersync(dex, &log)?; // bail: data too short

// after: route by topic0 to the correct parser
const PANCAKE_V3_SWAP_TOPIC: &str = "19b47279256b2a23a1665c810c8d55a1758940ee09377d4f8d26497a3577dc83";
const UNISWAP_V3_SWAP_TOPIC: &str = "c42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67";
let event = if log.topics[0].to_string().contains(PANCAKE_V3_SWAP_TOPIC) {
    parse_swap_event_hypersync(pancake_dex, &log)?
} else if log.topics[0].to_string().contains(UNISWAP_V3_SWAP_TOPIC) {
    parse_uniswap_v3_swap(dex, &log)?
} else { anyhow::bail!("unknown swap topic"); };
Defensive patterns

Strategy: validation

Validate before calling

const PANCAKE_V3_SWAP_TOPIC: &str = "19b47279256b2a23a1665c810c8d55a1758940ee09377d4f8d26497a3577dc83";
pub fn can_parse_pancake_swap(log: &HypersyncLog) -> bool {
    let topic_ok = log.topics.first()
        .and_then(|t| t.as_ref())
        .map(|t| t.to_string().contains(PANCAKE_V3_SWAP_TOPIC))
        .unwrap_or(false);
    let data_ok = log.data.as_ref()
        .map(|d| d.as_ref().len() >= 7 * 32)
        .unwrap_or(false);
    topic_ok && data_ok
}

Type guard

fn is_full_pancake_swap_data(log: &HypersyncLog) -> bool {
    log.data.as_ref().map(|d| d.as_ref().len() >= 224).unwrap_or(false)
}

Try / catch

match parse_swap_event_hypersync(dex, &log) {
    Ok(event) => store(event),
    Err(e) if e.to_string().contains("too short") => {
        tracing::warn!(tx = ?log.transaction_hash, "short swap data — likely Uniswap V3 log routed to PancakeSwap parser; skipping");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling parse_swap_event_hypersync with a HypersyncLog whose topic0 matches the PancakeSwap V3 Swap signature hash (0x19b47279...) but whose `data` hex is shorter than 224 bytes (7 x 32 bytes) — e.g. a truncated 5-word Uniswap V3 layout, a partially fetched log, or corrupted data.

Common situations: Indexing BSC pools with a query that mixes Uniswap V3 and PancakeSwap V3 logs; copying a Uniswap V3 Swap log fixture into PancakeSwap test data; HyperSync responses truncated by size limits or network errors; manually constructing test logs with incomplete data fields.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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