nautechsystems/nautilus_trader · error

PairCreated event data too short: expected at least 32 bytes

Error message

PairCreated event data too short: expected at least 32 bytes, was {}

What it means

parse_pool_created_event_hypersync validates that the PairCreated event's data section contains at least 32 bytes — the right-aligned pair address word. It throws when the data payload is present but too short to contain the pair address, indicating a malformed or truncated log.

Source

Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v2/pool_created.rs:54

/// - topic1: token0 (indexed)
/// - topic2: token1 (indexed)
/// - data: pair address (32 bytes) + pair count (32 bytes)
///
/// # Errors
///
/// Returns an error if the log parsing fails or if the event data is invalid.
pub fn parse_pool_created_event_hypersync(log: HypersyncLog) -> anyhow::Result<PoolCreatedEvent> {
    validate_event_signature_hash("PairCreatedEvent", PAIR_CREATED_EVENT_SIGNATURE_HASH, &log)?;

    let block_number = extract_block_number(&log)?;
    let token0 = extract_address_from_topic(&log, 1, "token0")?;
    let token1 = extract_address_from_topic(&log, 2, "token1")?;

    if let Some(data) = log.data {
        // Data contains: [pair_address (32 bytes), pair_count (32 bytes)]
        let data_bytes = data.as_ref();

        anyhow::ensure!(
            data_bytes.len() >= 32,
            "PairCreated event data too short: expected at least 32 bytes, was {}",
            data_bytes.len()
        );

        // Extract pair address (first 32 bytes, address is right-aligned)
        let pair_address = Address::from_slice(&data_bytes[12..32]);
        let pool_identifier = PoolIdentifier::Address(Ustr::from(&pair_address.to_string()));

        Ok(PoolCreatedEvent::new(
            block_number,
            token0,
            token1,
            pair_address,
            pool_identifier, // For V2/V3, pool_identifier = pool_address
            None,            // V2 has no fee tiers (fixed 0.3%)
            None,            // V2 has no tick spacing (CPAMM)
        ))

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify log.data is a full 32+ byte payload (pair address word) before calling
  2. Re-fetch the log; if persistent, the contract is non-standard — confirm the factory address and event ABI
  3. Ensure the event signature check routed the log to the UniswapV2 PairCreated parser, not a fork's variant
  4. Truncate gracefully: if data includes the extra uint256 word, ensure it is not cut mid-record

Example fix

// before
let data = log.data.as_ref().unwrap();
let pair = parse_pool_created_event_hypersync(&log)?;
// after
if log.data.as_ref().map_or(true, |d| d.len() < 32) { skip_record(); continue; }
let pair = parse_pool_created_event_hypersync(&log)?;
Defensive patterns

Strategy: validation

Validate before calling

fn pair_data_ok(log: &Log) -> bool {
    log.data.as_ref().map_or(false, |d| d.len() >= 32)
}

Try / catch

if !pair_data_ok(&log) { skip_malformed_record(&log); return Ok(()); }
let pool = parse_pool_created_event_hypersync(&log)?;

Prevention

When it happens

Trigger: Calling parse_pool_created_event_hypersync with a log whose data field is 1–31 bytes long, e.g. truncated record from hypersync or a non-standard factory contract emitting shorter data.

Common situations: Indexing an unofficial factory fork with a different PairCreated layout; corrupted/partial records from the data provider; decoding a similarly named but different event that slipped through signature checks.

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