{"record":{"id":"e91126ba92b6836f","repo":"nautechsystems/nautilus_trader","slug":"missing-description-address-in-topic-topic-index","errorCode":null,"errorMessage":"Missing {description} address in topic{topic_index} when parsing event","messagePattern":"Missing (.+?) address in topic(.+?) when parsing event","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/hypersync/log.rs","lineNumber":35,"sourceCode":"use nautilus_core::hex;\n\nuse super::HypersyncLog;\nuse crate::exchanges::parsing::core;\n\n/// Extracts an address from a specific topic in a log entry\n///\n/// # Errors\n///\n/// Returns an error if the topic at the specified index is not present in the log.\npub fn extract_address_from_topic(\n    log: &HypersyncLog,\n    topic_index: usize,\n    description: &str,\n) -> anyhow::Result<Address> {\n    match log.topics.get(topic_index).and_then(|t| t.as_ref()) {\n        Some(topic) => core::extract_address_from_bytes(topic.as_ref()),\n        None => {\n            anyhow::bail!(\"Missing {description} address in topic{topic_index} when parsing event\")\n        }\n    }\n}\n\n/// Extracts the transaction hash from a log entry\n///\n/// # Errors\n///\n/// Returns an error if the transaction hash is not present in the log.\npub fn extract_transaction_hash(log: &HypersyncLog) -> anyhow::Result<String> {\n    log.transaction_hash\n        .as_ref()\n        .map(ToString::to_string)\n        .ok_or_else(|| anyhow::anyhow!(\"Missing transaction hash in log\"))\n}\n\n/// Extracts the transaction index from a log entry\n///","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/hypersync/log.rs#L17-L53","documentation":"extract_address_from_topic pulls an Address out of a hypersync log's topics array at a given index. Event topics are optional (a topic slot may be absent or None), but the caller requires the address at that position — so when the topic is missing, the function bails with this message naming the description (e.g. which address) and the topic index.","triggerScenarios":"Calling extract_address_from_topic(log, topic_index, description) where log.topics has fewer entries than topic_index+1 or topics[topic_index] is None — typically extracting a sender/recipient address from topic1/topic2/topic3 of an event whose actual signature has fewer indexed parameters.","commonSituations":"Decoding logs with the wrong event ABI (topic index beyond the event's indexed params); anonymous events or events with optional indexed fields; filtering hypersync logs whose signatures differ from the assumed ERC-20-style Transfer(topic0, from topic1, to topic2); malformed/partial log data from the provider.","solutions":["Verify the event ABI: confirm the event at topic0 actually has an indexed parameter at the requested topic index before extracting.","Check topics.len() and topics[i].is_some() before calling, or handle the error as 'not this event' and skip the log.","Ensure the log filter/query targets the correct event signature so topic layout matches expectations.","If the event legitimately has optional topics, use an overload/fallback that treats a missing topic as absent instead of an error."],"exampleFix":"// before\nlet from = extract_address_from_topic(&log, 1, \"sender\")?; // panics into bail if topics[1] absent\n// after\nif log.topics.get(1).and_then(|t| t.as_ref()).is_some() {\n    let from = extract_address_from_topic(&log, 1, \"sender\")?;\n} else {\n    return Ok(None); // not the expected event layout\n}","handlingStrategy":"validation","validationCode":"fn topic_present(log: &Log, idx: usize) -> bool {\n    log.topics.get(idx).and_then(|t| t.as_ref()).is_some()\n}\n// only extract when topic_present(&log, topic_index)","typeGuard":"fn topic_at<'a>(log: &'a Log, idx: usize) -> Option<&'a [u8]> {\n    log.topics.get(idx).and_then(|t| t.as_ref()).map(|t| t.as_ref())\n}","tryCatchPattern":"match extract_address_from_topic(&log, 1, \"sender\") {\n    Err(e) if e.to_string().starts_with(\"Missing \") => /* treat as non-matching event, skip log */,\n    Err(e) => return Err(e),\n    Ok(addr) => addr,\n}","preventionTips":["Match logs against the exact event signature (topic0) before reading indexed topics","Keep topic-index constants in one place tied to the event ABI definition","Filter hypersync queries by event signature so logs have the expected topic layout","Handle optional/anonymous events explicitly rather than assuming ERC-20-style topic layout"],"tags":["rust","hypersync","event-log","missing-topic"],"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"}