nautechsystems/nautilus_trader · error

unexpected event signature {event_signature} for log {log:?}

Error message

unexpected event signature {event_signature} for log {log:?}

What it means

While syncing pool event logs (swap/mint/burn/flash events) from HyperSync, a log's decoded event signature matched none of the registered signatures for that DEX/pool. Since the client only expects known pool event signatures, any other signature is treated as unexpected data and the sync fails with the hex signature and the offending log.

Source

Thrown at crates/adapters/blockchain/src/data/core.rs:770

                            fee_protocol_collect_event.block_number
                        )
                    })?;
                protocol_collect_batch.push(collect);
            } else if flash_sig_bytes.as_ref().is_some_and(|sig| sig.as_slice() == event_sig_bytes) {
                let parse_fn = dex_extended
                    .parse_flash_event_hypersync_fn
                    .context("missing flash event parser")?;
                let flash_event = parse_fn(dex_extended.dex.clone(), &log)
                    .context("failed to parse flash event")?;
                let flash = self
                    .process_pool_flash_event(&flash_event, &pool)
                    .with_context(|| {
                        format!("failed to process flash event at block {}", flash_event.block_number)
                    })?;
                flash_batch.push(flash);
            } else {
                let event_signature = hex::encode(event_sig_bytes);
                anyhow::bail!("unexpected event signature {event_signature} for log {log:?}");
            }

            // Check if we've moved beyond stale data (transition point for strategy change)
            if !beyond_stale_data
                && last_block_across_pool_events_table
                    .is_some_and(|table_max| block_number > table_max)
            {
                log::debug!(
                    "Crossed beyond stale data at block {block_number} - flushing current batches with ON CONFLICT, then switching to COPY"
                );

                // Flush all batches with ON CONFLICT to handle any remaining duplicates
                self.flush_event_batches(
                    EVENT_BATCH_SIZE,
                    &mut block_batch,
                    &mut swap_batch,
                    &mut liquidity_batch,
                    &mut collect_batch,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the DEX type and version for this pool matches a supported implementation
  2. Register the missing event signature for the DEX if it is a supported variant
  3. Filter/skip unknown logs if your pool contract emits additional events
  4. Update the adapter/library to a version supporting the new event signatures

Example fix

// before
register_dex(DexType::UnknownFork) // signatures don't match pool logs
// after
register_dex(DexType::UniswapV3)   // correct DEX with matching event signatures
Defensive patterns

Strategy: try-catch

Validate before calling

// before syncing, confirm the pool's contract emits the DEX's expected event signatures
let known: [[u8;32];4] = dex.event_signatures();
if !known.contains(&log.topics()[0]) { skip_or_register(log); }

Try / catch

match core.sync_pool_events(pool, from, to).await {
    Err(e) if e.to_string().contains("unexpected event signature") => {
        log::warn!("skipping pool with unknown events: {e}");
    }
    r => r?,
}

Prevention

When it happens

Trigger: sync_pool_events (also via bootstrap_latest_pool_profiler) encounters a log on the pool address whose topic0 is not one of the DEX's registered event signatures — e.g. a non-standard pool contract, a fork with extra events, or a newly deployed DEX version with different event hashes.

Common situations: Indexing a pool on a DEX fork or newer version whose event topics differ; unregistered custom pool; a DEX upgrade changing event signatures without updating the adapter; logs from unrelated contracts sharing the pool address.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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