nautechsystems/nautilus_trader · error
Invalid contract address length: expected {} bytes, was {}
Error message
Invalid contract address length: expected {} bytes, was {} What it means
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.
Source
Thrown at crates/adapters/blockchain/src/rpc/log.rs:110
/// # Errors
///
/// Returns an error if the log index is missing or cannot be parsed.
pub fn extract_log_index(log: &RpcLog) -> anyhow::Result<u32> {
let hex = log
.log_index
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Missing log index"))?;
parse_hex_u32(hex)
}
/// Extract contract address from RPC log.
///
/// # Errors
///
/// Returns an error if the address is invalid.
pub fn extract_address(log: &RpcLog) -> anyhow::Result<Address> {
let bytes = decode_hex(&log.address)?;
anyhow::ensure!(
bytes.len() == Address::len_bytes(),
"Invalid contract address length: expected {} bytes, was {}",
Address::len_bytes(),
bytes.len()
);
Ok(Address::from_slice(&bytes))
}
/// Extract topic bytes at index.
///
/// # Errors
///
/// Returns an error if the topic at the specified index is missing.
pub fn extract_topic_bytes(log: &RpcLog, index: usize) -> anyhow::Result<Vec<u8>> {
let hex = log
.topics
.get(index)
.ok_or_else(|| anyhow::anyhow!("Missing topic at index {index}"))?;View on GitHub (pinned to 18893faf8b)
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.
Example fix
// before
let addr = extract_address(&log)?;
// after
let raw = decode_hex(&log.address)?;
if raw.len() != 20 {
eprintln!("skipping log with malformed address: {:?}", log.address);
return Ok(None);
}
let addr = extract_address(&log)?; Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_address_hex(s: &str) -> bool {
decode_hex(s).map(|b| b.len() == 20).unwrap_or(false)
} Type guard
fn is_valid_address(log: &RpcLog) -> bool {
decode_hex(&log.address).map_or(false, |b| b.len() == Address::len_bytes())
} Try / catch
match extract_address(&log) {
Ok(a) => a,
Err(e) => { log::warn!("bad address {:?}: {e}", log.address); return Ok(None); }
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Nonstandard or L2-sidecar RPCs returning addresses in unexpected encodings, accidentally passing a topic (32 bytes) as the address, or malformed/offline test fixtures.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Ethereum address must start with '0x': {address}
- Missing {description} address in topic{index}
- Topic must be at least 32 bytes, was {}
- Invalid receipt log address
- Blockchain address '{address}' is incorrect: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/25143dab978e5453.
Report an issue: GitHub.