nautechsystems/nautilus_trader · error

RPC snapshot contains duplicate ticks

Error message

RPC snapshot contains duplicate ticks

What it means

The on-chain snapshot's ticks are collected into a map keyed by tick value; if the resulting map is smaller than the raw tick list, the RPC returned the same tick more than once. Since a Uniswap V3 tick bitmap has unique entries, duplicates indicate a malformed snapshot, so validation bails before restore.

Source

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

        if actual_positions.len() != snapshot.positions.len()
            || actual_positions != expected_positions
        {
            anyhow::bail!(
                "RPC positions do not match the complete HyperSync topology: expected {} positions, received {}",
                expected_positions.len(),
                actual_positions.len()
            );
        }

        let actual_ticks: AHashMap<_, _> = snapshot
            .ticks
            .iter()
            .map(|tick| (tick.value, tick))
            .collect();

        if actual_ticks.len() != snapshot.ticks.len() {
            anyhow::bail!("RPC snapshot contains duplicate ticks");
        }

        let expected_tick_values = profiler.get_active_tick_values();
        if actual_ticks.len() != expected_tick_values.len() {
            anyhow::bail!(
                "RPC ticks do not match the complete HyperSync topology: expected {} ticks, received {}",
                expected_tick_values.len(),
                actual_ticks.len()
            );
        }

        for tick_value in expected_tick_values {
            let expected_tick = profiler
                .get_tick(tick_value)
                .with_context(|| format!("missing replay tick {tick_value}"))?;
            let actual_tick = actual_ticks
                .get(&tick_value)
                .with_context(|| format!("RPC snapshot omitted tick {tick_value}"))?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect snapshot.ticks for the duplicated tick values and check the fetch_snapshot implementation that produced them (pagination/Multicall chunking may double-count a boundary tick).
  2. Ensure the ticks requested from the pool contract are derived from the profiler's distinct active tick values (get_active_tick_values) without overlap.
  3. Upgrade/fix the univ3_pool snapshot reader for the specific DEX fork if its tick queries return duplicated entries.
  4. Re-run bootstrap against a different RPC endpoint to rule out endpoint-specific malformed responses.

Example fix

// before
let requested_ticks = ticks_from_raw_query; // may contain duplicates from overlapping chunks
// after
let requested_ticks: Vec<_> = requested_ticks.into_iter().map(|t| (t.value, t)).collect::<AHashMap<_,_>>().into_values().collect();
Defensive patterns

Strategy: try-catch

Validate before calling

// Deduplicate/detect duplicate ticks in a snapshot before use
let unique: std::collections::HashSet<i32> = snapshot.ticks.iter().map(|t| t.value).collect();
if unique.len() != snapshot.ticks.len() {
    // snapshot is malformed; do not restore
}

Type guard

fn has_unique_ticks(snapshot: &PoolSnapshot) -> bool {
    let mut seen = std::collections::HashSet::new();
    snapshot.ticks.iter().all(|t| seen.insert(t.value))
}

Try / catch

match bootstrap_result {
    Err(e) if e.to_string().contains("duplicate ticks") => {
        log::error!("RPC snapshot malformed (duplicate ticks): {e:#}");
        // re-fetch snapshot from a different endpoint or fail the bootstrap
    }
    other => other?,
}

Prevention

When it happens

Trigger: validate_rpc_snapshot_topology (invoked from construct_pool_profiler_from_hypersync_rpc after fetching the snapshot) receives a PoolSnapshot whose `ticks` vec contains two or more entries with the same `value`.

Common situations: A buggy or misbehaving RPC/contract reader aggregating ticks incorrectly; contract fetch_snapshot returning overlapping tick ranges (e.g. tick values not normalized by tick spacing); a custom fork's Multicall response parsed twice into the tick list.

Related errors


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