nautechsystems/nautilus_trader · error · anyhow::Error

Profiler watermark log has no event signature

Error message

Profiler watermark log has no event signature

What it means

The profiler watermark log must have at least one topic, since topic[0] is the event signature used to identify the pool event type. This error is thrown when the matched log has an empty topics array, so no event signature can be extracted.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:4241

        .block_hash
        .as_deref()
        .ok_or_else(|| anyhow::anyhow!("Profiler log has no block hash"))?;
    anyhow::ensure!(
        !log.removed
            && log_transaction_hash == transaction_hash
            && rpc_log::extract_block_number(log)? == position.number
            && rpc_log::extract_transaction_index(log)? == position.transaction_index
            && B256::from_str(log_block_hash)? == expected_block_hash,
        "Profiler log position does not match its ingestion watermark"
    );
    anyhow::ensure!(
        rpc_log::extract_address(log)? == pool_address,
        "Profiler watermark log did not come from expected pool {pool_address}"
    );
    let signature = log
        .topics
        .first()
        .ok_or_else(|| anyhow::anyhow!("Profiler watermark log has no event signature"))?;
    let supported =
        profiler_event_signatures(pool).any(|expected| expected.eq_ignore_ascii_case(signature));
    anyhow::ensure!(
        supported,
        "Profiler watermark log has an unsupported event signature"
    );
    Ok(())
}

fn profiler_event_signatures(pool: &Pool) -> impl Iterator<Item = &str> {
    [
        Some(pool.dex.swap_created_event.as_ref()),
        Some(pool.dex.mint_created_event.as_ref()),
        Some(pool.dex.burn_created_event.as_ref()),
        Some(pool.dex.collect_created_event.as_ref()),
        pool.dex.flash_created_event.as_deref(),
        pool.dex.fee_protocol_update_event.as_deref(),
        pool.dex.fee_protocol_collect_event.as_deref(),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check in a block explorer what event the log at position.log_index actually is; adjust the watermark to point at a standard event log.
  2. Verify the pool contract version still emits non-anonymous events; update the profiler if the contract changed.
  3. Confirm profiler_event_signatures configuration covers the event actually emitted by this pool.
  4. Use a fuller RPC provider if the topics array appears wrongly truncated.
Defensive patterns

Strategy: validation

Validate before calling

if log.topics.is_empty() {
    // not an identifiable event; skip or re-point the watermark
    return Err("log has no topics".into());
}

Type guard

fn has_event_signature(log: &Log) -> bool {
    !log.topics.is_empty()
}

Try / catch

match validate_watermark_signature(&log, pool) {
    Ok(()) => Ok(()),
    Err(e) if e.to_string().contains("no event signature") => skip_anonymous_log(e),
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Profiler validation on a log whose topics array is empty (topics.first() returns None) — e.g., an anonymous event or a data-only log emitted by the pool at the watermark index.

Common situations: The transaction at the watermark emitted an anonymous event (no indexed signature topic); the log_index points at a non-event log; a contract upgrade switched to anonymous events; provider returned a malformed/empty topics list.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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