nautechsystems/nautilus_trader · error

Missing {description} address in topic{index}

Error message

Missing {description} address in topic{index}

What it means

This error means the topic needed to extract an indexed address parameter was missing (extract_topic_bytes failed at the given index), so an address could not be recovered. It flattens the underlying missing-topic error into a message naming the parameter via the description argument (e.g. token0/token1 in AMM events).

Source

Thrown at crates/adapters/blockchain/src/rpc/log.rs:146

        .ok_or_else(|| anyhow::anyhow!("Missing topic at index {index}"))?;
    decode_hex(hex)
}

/// Extract address from topic at index.
///
/// In Ethereum event logs, indexed address parameters are stored as 32-byte
/// values with the 20-byte address right-aligned (padded with zeros on the left).
///
/// # Errors
///
/// Returns an error if the topic is missing or the address extraction fails.
pub fn extract_address_from_topic(
    log: &RpcLog,
    index: usize,
    description: &str,
) -> anyhow::Result<Address> {
    let bytes = extract_topic_bytes(log, index)
        .map_err(|_| anyhow::anyhow!("Missing {description} address in topic{index}"))?;
    anyhow::ensure!(
        bytes.len() >= 32,
        "Topic must be at least 32 bytes, was {}",
        bytes.len()
    );
    Ok(Address::from_slice(&bytes[12..32]))
}

/// Extract data bytes from RPC log.
///
/// # Errors
///
/// Returns an error if the hex decoding fails.
pub fn extract_data_bytes(log: &RpcLog) -> anyhow::Result<Vec<u8>> {
    decode_hex(&log.data)
}

/// Validate event signature from topic0.

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Confirm the event ABI: the parameter must be indexed and located at the requested topic position.
  2. Verify topic0 matches the expected event signature before extracting address topics.
  3. Check log.topics.len() covers the requested index (index+1 topics needed, since topic0 is the signature).
  4. Note the original cause is discarded by map_err(|_|) — check topics length to distinguish missing topic from decode failure.

Example fix

// before
let token0 = extract_address_from_topic(&log, 1, "token0")?;
// after
if log.topics.len() < 2 {
    return Err(anyhow::anyhow!("log has {} topics; expected >= 2", log.topics.len()));
}
let token0 = extract_address_from_topic(&log, 1, "token0")?;
Defensive patterns

Strategy: validation

Validate before calling

fn has_address_topic(log: &RpcLog, index: usize) -> bool {
    log.topics.len() > index
        && log.topics[index].trim_start_matches("0x").len() == 64
}

Type guard

fn address_topic_ok(log: &RpcLog, i: usize) -> bool {
    log.topics.get(i).map_or(false, |t| t.trim_start_matches("0x").chars().all(|c| c.is_ascii_hexdigit()) && t.trim_start_matches("0x").len() == 64)
}

Try / catch

let token = match extract_address_from_topic(&log, 1, "token0") {
    Ok(a) => a,
    Err(e) => { log::warn!("no token0 topic: {e}"); return Ok(()); }
};

Prevention

When it happens

Trigger: Calling extract_address_from_topic with an index beyond the log's topic count — e.g. requesting topic1 for an anonymous event or an event where that parameter is not indexed.

Common situations: Wrong event-type assumptions when decoding AMM pool logs, contract versions with different indexed parameters, or mismatched topic positions after contract upgrades.

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/ea2d6368a90b6e53. Report an issue: GitHub.