nautechsystems/nautilus_trader · error
Invalid event signature for '{event_name}': expected {expect
Error message
Invalid event signature for '{event_name}': expected {expected_hex}, was {actual_hex} What it means
validate_signature_bytes compares the event signature topic bytes (hex-encoded) against the expected keccak256 signature hash for the named event and throws when they differ. This catches decoding a log that is not actually the event the caller assumed, preventing misparsed fields.
Source
Thrown at crates/adapters/blockchain/src/exchanges/parsing/core.rs:90
Ok(i32::from_be_bytes(bytes[28..32].try_into()?))
}
/// Validate event signature matches expected hash.
///
/// The first topic (topic0) of an Ethereum event log contains the keccak256 hash
/// of the event signature. This function validates that the actual signature
/// matches the expected one.
///
/// # Errors
///
/// Returns an error if the signatures don't match.
pub fn validate_signature_bytes(
actual: &[u8],
expected_hex: &str,
event_name: &str,
) -> anyhow::Result<()> {
let actual_hex = hex::encode(actual);
anyhow::ensure!(
actual_hex == expected_hex,
"Invalid event signature for '{event_name}': expected {expected_hex}, was {actual_hex}",
);
Ok(())
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
#[rstest]
fn test_extract_address_token0() {
// token0 address from PoolCreated event topic1 at block 185
let bytes = hex::decode("0000000000000000000000002e5353426c89f4ecd52d1036da822d47e73376c4")
.unwrap();
View on GitHub (pinned to 18893faf8b)
Solutions
- Compare the actual hex in the error with the keccak256 of the event signature you intended; correct expected_hex or route the log to the right parser
- Verify topic0 is the signature topic (index 0), not a data or param topic
- Recompute the expected hash from the contract's ABI if it was recently upgraded
- Add explicit dispatch by topic0 before invoking the specific event parser
Example fix
// before
validate_signature_bytes(topic0, UNISWAP_V3_SWAP_SIG, "Swap")?;
// after
if hex::encode(topic0) == PANCAKE_V3_SWAP_SIG {
validate_signature_bytes(topic0, PANCAKE_V3_SWAP_SIG, "Swap")?;
} else {
return Err(anyhow::anyhow!("unsupported swap signature"));
} Defensive patterns
Strategy: validation
Validate before calling
fn signature_matches(topic0: &[u8], expected_hex: &str) -> bool {
hex::encode(topic0) == expected_hex
} Try / catch
match validate_signature_bytes(topic0, EXPECTED_SWAP_SIG, "Swap") {
Ok(()) => decode_swap(),
Err(e) if e.to_string().contains("Invalid event signature") => route_to_correct_parser(topic0),
Err(e) => return Err(e),
} Prevention
- Dispatch parsers by topic0 before calling any event-specific decoder
- Keep expected signature hashes generated from the contract ABI, not hand-copied
- When indexing multiple DEX forks, maintain a topic0 -> parser map
- Log the actual hex on mismatch to speed up diagnosis
When it happens
Trigger: Calling validate_signature_bytes with the signature topic of a different event, e.g. passing an Uniswap V3 swap topic to a PancakeSwap V3 parser, or a wrong expected_hex constant; also when topic0 bytes are truncated so the hex never matches.
Common situations: Indexing multiple DEX forks whose events share names but different signatures (e.g. Uniswap V3 vs PancakeSwap V3 swap); a contract upgrade changed the event ABI; copy-pasted wrong expected hash.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Topic must be at least 32 bytes, was {}
- PairCreated event data too short: expected at least 32 bytes
- Ethereum address must start with '0x': {address}
- Missing data in swap event log
- Missing data in pair created event log
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f1af5053728cedf7.
Report an issue: GitHub.