nautechsystems/nautilus_trader · error
Failed to decode swap event data: {e}
Error message
Failed to decode swap event data: {e} What it means
The same hypersync swap parser failed at the ABI decode stage: the data passed the 160-byte pre-check but <SwapEventData as SolType>::abi_decode rejected it. The inner alloy decoding error is embedded so developers can see the exact word/type mismatch.
Source
Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/swap.rs:74
/// 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();
// Validate if data contains 5 parameters of 32 bytes each
if data_bytes.len() < 5 * 32 {
anyhow::bail!("Swap event data is too short");
}
// Decode the data using the SwapEventData struct
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 _ = decoded.amount0;
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)?,
extract_transaction_index(log)?,
extract_log_index(log)?,
sender,
recipient,View on GitHub (pinned to 18893faf8b)
Solutions
- Print the failing data hex and compare word-by-word against the canonical V3 Swap layout (amount0, amount1, sqrtPriceX96, liquidity, tick)
- Confirm the log's topic0 equals the canonical V3 Swap signature hash
- Validate the hex payload decodes cleanly (even length, valid hex) before ABI decoding
- Regenerate SwapEventData bindings if the target contract is a fork with an altered event
- Treat undecodable logs as skip-and-log instead of failing block ingestion
Example fix
// before
let decoded = match <SwapEventData as SolType>::abi_decode(data_bytes) {
Ok(d) => d,
Err(e) => anyhow::bail!("Failed to decode swap event data: {e}"),
};
// after
let decoded = match <SwapEventData as SolType>::abi_decode(data_bytes) {
Ok(d) => d,
Err(e) => {
tracing::warn!(%e, "undecodable swap log skipped");
return Ok(None);
}
}; Defensive patterns
Strategy: try-catch
Validate before calling
if log.topic0 != SWAP_V3_TOPIC0 || data_bytes.len() < 160 { skip(); }
// additionally validate hex payload:
if data_hex.len() % 2 != 0 { skip(); } Try / catch
match parse_swap_event_hypersync(&dex, &log) {
Ok(ev) => handle(ev),
Err(e) => { tracing::warn!(%e, data = %hex, "undecodable swap log skipped"); Ok(None) }
} Prevention
- Diff failing payloads word-by-word against the canonical Swap layout
- Verify topic0 before decoding
- Regenerate bindings for forked contracts
- Make undecodable logs non-fatal in ingestion loops
When it happens
Trigger: Data is >= 160 bytes but the word layout does not match SwapEventData — extra leading bytes, non-canonical padding, or a fork contract with a modified Swap schema.
Common situations: Decoding logs from a modified Uniswap fork; provider returning hex with wrong encoding (odd-length hex, non-hex chars); decoding events from unrelated contracts that share a partial topic0.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Swap event data is too short
- Missing tickLower in topic2 when parsing collect event
- Missing tickUpper in topic3 when parsing collect event
- SetFeeProtocol event data is too short
- Failed to decode SetFeeProtocol event data: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4467250d8caae6a1.
Report an issue: GitHub.