nautechsystems/nautilus_trader · error
Missing tickLower in topic2 when parsing collect event
Error message
Missing tickLower in topic2 when parsing collect event
What it means
This error is raised by parse_collect_event_hypersync when a Uniswap V3 Collect event log fetched via HyperSync has no topic at index 2. The Collect event encodes tickLower as an indexed int24 in topic2, so without it the position's lower tick boundary cannot be recovered and parsing must abort.
Source
Thrown at crates/adapters/blockchain/src/exchanges/parsing/uniswap_v3/collect.rs:69
///
/// # Panics
///
/// Panics if the contract address is not set in the log.
pub fn parse_collect_event_hypersync(
dex: SharedDex,
log: &HypersyncLog,
) -> anyhow::Result<CollectEvent> {
validate_event_signature_hash("Collect", COLLECT_EVENT_SIGNATURE_HASH, log)?;
let owner = extract_address_from_topic(log, 1, "owner")?;
// Extract int24 tickLower from topic2 (stored as a 32-byte padded value)
let tick_lower = match log.topics.get(2).and_then(|t| t.as_ref()) {
Some(topic) => {
let tick_lower_bytes: [u8; 32] = topic.as_ref().try_into()?;
i32::from_be_bytes(tick_lower_bytes[28..32].try_into()?)
}
None => anyhow::bail!("Missing tickLower in topic2 when parsing collect event"),
};
// Extract int24 tickUpper from topic3 (stored as a 32-byte padded value)
let tick_upper = match log.topics.get(3).and_then(|t| t.as_ref()) {
Some(topic) => {
let tick_upper_bytes: [u8; 32] = topic.as_ref().try_into()?;
i32::from_be_bytes(tick_upper_bytes[28..32].try_into()?)
}
None => anyhow::bail!("Missing tickUpper in topic3 when parsing collect event"),
};
if let Some(data) = &log.data {
let data_bytes = data.as_ref();
// Validate if data contains 3 parameters of 32 bytes each
if data_bytes.len() < 3 * 32 {
anyhow::bail!("Collect event data is too short");
}View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the log's topic0 matches the Collect event signature before calling parse_collect_event_hypersync
- Check log.topics.len() >= 4 and that each slot is Some before parsing
- Ensure the HyperSync query/request is scoped to the UniswapV3Pool Collect event ABI
- Log the raw topics array to confirm which event was actually delivered
Example fix
// before
let event = parse_collect_event_hypersync(&dex, &log)?;
// after
if log.topics.len() < 4 || log.topics[0].as_deref() != Some(&COLLECT_TOPIC0) {
return Ok(None); // skip non-Collect logs
}
let event = parse_collect_event_hypersync(&dex, &log)?; Defensive patterns
Strategy: validation
Validate before calling
const COLLECT_TOPIC0: [u8; 32] = <Collect as SolEvent>::SIGNATURE_HASH;
fn has_collect_topics(log: &Log) -> bool {
log.topics.len() >= 4
&& log.topics[0].as_deref() == Some(&COLLECT_TOPIC0)
&& log.topics.iter().skip(1).all(|t| t.is_some())
}
// if !has_collect_topics(&log) { skip or re-fetch } Type guard
fn is_collect_log(log: &Log) -> bool {
log.topics.len() >= 4 && log.topics[0].is_some() && log.topics[2].is_some()
} Try / catch
match parse_collect_event_hypersync(&dex, &log) {
Ok(event) => handle(event),
Err(e) if e.to_string().contains("Missing tickLower") => {
tracing::warn!("Collect log missing topic2, skipping: {e}");
}
Err(e) => return Err(e),
} Prevention
- Always filter HyperSync/RPC queries by the exact Collect event topic0
- Validate topic count and presence before invoking parsers
- Write a round-trip test that encodes a Collect event and parses it back
- Pin the pool ABI version your adapter expects
When it happens
Trigger: Passing a log whose topics array has fewer than 3 entries, a log for a different event with only 2 indexed parameters, or a malformed HyperSync response where topics[2] is null.
Common situations: Subscribing with an over-broad topic0 filter that matches non-Collect events; upstream provider delivering truncated topic arrays; testing with hand-crafted logs missing indexed fields.
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
- Missing tickUpper in topic3 when parsing collect event
- Missing tickLower in topic2 when parsing burn event
- Missing fee in topic3 when parsing pool created event
- Swap event data is too short
- Failed to decode swap event data: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4e456a9ad982ca41.
Report an issue: GitHub.