{"record":{"id":"25143dab978e5453","repo":"nautechsystems/nautilus_trader","slug":"invalid-contract-address-length-expected-bytes","errorCode":null,"errorMessage":"Invalid contract address length: expected {} bytes, was {}","messagePattern":"Invalid contract address length: expected (.+?) bytes, was (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/log.rs","lineNumber":110,"sourceCode":"/// # Errors\n///\n/// Returns an error if the log index is missing or cannot be parsed.\npub fn extract_log_index(log: &RpcLog) -> anyhow::Result<u32> {\n    let hex = log\n        .log_index\n        .as_ref()\n        .ok_or_else(|| anyhow::anyhow!(\"Missing log index\"))?;\n    parse_hex_u32(hex)\n}\n\n/// Extract contract address from RPC log.\n///\n/// # Errors\n///\n/// Returns an error if the address is invalid.\npub fn extract_address(log: &RpcLog) -> anyhow::Result<Address> {\n    let bytes = decode_hex(&log.address)?;\n    anyhow::ensure!(\n        bytes.len() == Address::len_bytes(),\n        \"Invalid contract address length: expected {} bytes, was {}\",\n        Address::len_bytes(),\n        bytes.len()\n    );\n    Ok(Address::from_slice(&bytes))\n}\n\n/// Extract topic bytes at index.\n///\n/// # Errors\n///\n/// Returns an error if the topic at the specified index is missing.\npub fn extract_topic_bytes(log: &RpcLog, index: usize) -> anyhow::Result<Vec<u8>> {\n    let hex = log\n        .topics\n        .get(index)\n        .ok_or_else(|| anyhow::anyhow!(\"Missing topic at index {index}\"))?;","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/log.rs#L92-L128","documentation":"This error means the decoded address bytes from the RpcLog's address field did not have exactly 20 bytes (Address::len_bytes()), the canonical Ethereum address length. extract_address decodes the hex and enforces the length before constructing the Address, rejecting truncated, padded, or over-long values rather than truncating silently.","triggerScenarios":"Calling extract_address on a log whose address field decodes to fewer or more than 20 bytes — e.g. an empty string, a checksummed string with characters the hex decoder rejects, or a nonstandard provider returning full-width or partial addresses.","commonSituations":"Nonstandard or L2-sidecar RPCs returning addresses in unexpected encodings, accidentally passing a topic (32 bytes) as the address, or malformed/offline test fixtures.","solutions":["Log the raw address string and confirm it decodes to exactly 40 hex characters (20 bytes).","If the provider returns a different encoding, normalize it to 20-byte form before calling extract_address.","Check you are reading log.address and not a topic or data field.","Reject or quarantine logs with malformed addresses instead of unwrapping."],"exampleFix":"// before\nlet addr = extract_address(&log)?;\n// after\nlet raw = decode_hex(&log.address)?;\nif raw.len() != 20 {\n    eprintln!(\"skipping log with malformed address: {:?}\", log.address);\n    return Ok(None);\n}\nlet addr = extract_address(&log)?;","handlingStrategy":"validation","validationCode":"fn is_valid_address_hex(s: &str) -> bool {\n    decode_hex(s).map(|b| b.len() == 20).unwrap_or(false)\n}","typeGuard":"fn is_valid_address(log: &RpcLog) -> bool {\n    decode_hex(&log.address).map_or(false, |b| b.len() == Address::len_bytes())\n}","tryCatchPattern":"match extract_address(&log) {\n    Ok(a) => a,\n    Err(e) => { log::warn!(\"bad address {:?}: {e}\", log.address); return Ok(None); }\n}","preventionTips":["Check addresses decode to exactly 40 hex characters.","Do not pass topics or data fields where address is expected.","Normalize provider-specific encodings to 20-byte form.","Quarantine logs with malformed addresses."],"tags":["blockchain","ethereum","address","validation"],"backgroundTag":"invalid-argument-value","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"}