{"record":{"id":"ea2d6368a90b6e53","repo":"nautechsystems/nautilus_trader","slug":"missing-description-address-in-topic-index","errorCode":null,"errorMessage":"Missing {description} address in topic{index}","messagePattern":"Missing (.+?) address in topic(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/log.rs","lineNumber":146,"sourceCode":"        .ok_or_else(|| anyhow::anyhow!(\"Missing topic at index {index}\"))?;\n    decode_hex(hex)\n}\n\n/// Extract address from topic at index.\n///\n/// In Ethereum event logs, indexed address parameters are stored as 32-byte\n/// values with the 20-byte address right-aligned (padded with zeros on the left).\n///\n/// # Errors\n///\n/// Returns an error if the topic is missing or the address extraction fails.\npub fn extract_address_from_topic(\n    log: &RpcLog,\n    index: usize,\n    description: &str,\n) -> anyhow::Result<Address> {\n    let bytes = extract_topic_bytes(log, index)\n        .map_err(|_| anyhow::anyhow!(\"Missing {description} address in topic{index}\"))?;\n    anyhow::ensure!(\n        bytes.len() >= 32,\n        \"Topic must be at least 32 bytes, was {}\",\n        bytes.len()\n    );\n    Ok(Address::from_slice(&bytes[12..32]))\n}\n\n/// Extract data bytes from RPC log.\n///\n/// # Errors\n///\n/// Returns an error if the hex decoding fails.\npub fn extract_data_bytes(log: &RpcLog) -> anyhow::Result<Vec<u8>> {\n    decode_hex(&log.data)\n}\n\n/// Validate event signature from topic0.","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/log.rs#L128-L164","documentation":"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).","triggerScenarios":"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.","commonSituations":"Wrong event-type assumptions when decoding AMM pool logs, contract versions with different indexed parameters, or mismatched topic positions after contract upgrades.","solutions":["Confirm the event ABI: the parameter must be indexed and located at the requested topic position.","Verify topic0 matches the expected event signature before extracting address topics.","Check log.topics.len() covers the requested index (index+1 topics needed, since topic0 is the signature).","Note the original cause is discarded by map_err(|_|) — check topics length to distinguish missing topic from decode failure."],"exampleFix":"// before\nlet token0 = extract_address_from_topic(&log, 1, \"token0\")?;\n// after\nif log.topics.len() < 2 {\n    return Err(anyhow::anyhow!(\"log has {} topics; expected >= 2\", log.topics.len()));\n}\nlet token0 = extract_address_from_topic(&log, 1, \"token0\")?;","handlingStrategy":"validation","validationCode":"fn has_address_topic(log: &RpcLog, index: usize) -> bool {\n    log.topics.len() > index\n        && log.topics[index].trim_start_matches(\"0x\").len() == 64\n}","typeGuard":"fn address_topic_ok(log: &RpcLog, i: usize) -> bool {\n    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)\n}","tryCatchPattern":"let token = match extract_address_from_topic(&log, 1, \"token0\") {\n    Ok(a) => a,\n    Err(e) => { log::warn!(\"no token0 topic: {e}\"); return Ok(()); }\n};","preventionTips":["Confirm the parameter is indexed in the event ABI.","Verify topic0 matches the expected event before extracting.","Ensure topics.len() > index (topic0 is the signature).","Note extract_address_from_topic discards the root cause; pre-check topics yourself."],"tags":["blockchain","ethereum","topics","address"],"backgroundTag":"missing-required-argument","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}