nautechsystems/nautilus_trader · error · anyhow::Error

Ethereum address must start with '0x': {address}

Error message

Ethereum address must start with '0x': {address}

What it means

validate_address parses an EVM address string into an alloy Address. It first requires the '0x' prefix, then validates length, hex characters, and checksum via Address::from_str. A missing prefix fails immediately with this error.

Source

Thrown at crates/model/src/defi/validation.rs:38

//! blockchain identifiers.

use std::str::FromStr;

use alloy_primitives::Address;

/// Validates an Ethereum address format, checksum, and returns the parsed address.
///
/// # Errors
///
/// This function returns an error if:
/// - The address does not start with the `0x` prefix.
/// - The address has invalid length (must be 42 characters including `0x`).
/// - The address contains invalid hexadecimal characters.
/// - The address has an incorrect checksum (for checksummed addresses).
pub fn validate_address(address: &str) -> anyhow::Result<Address> {
    // Check if the address starts with "0x"
    if !address.starts_with("0x") {
        anyhow::bail!("Ethereum address must start with '0x': {address}");
    }

    // Check if the address is valid
    let parsed_address = Address::from_str(address)
        .map_err(|e| anyhow::anyhow!("Blockchain address '{address}' is incorrect: {e}"))?;

    // Check if checksum is valid
    Address::parse_checksummed(address, None)
        .map_err(|_| anyhow::anyhow!("Blockchain address '{address}' has incorrect checksum"))?;

    Ok(parsed_address)
}

#[cfg(test)]
mod tests {
    use rstest::rstest;

    use super::*;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Normalize the input: trim whitespace and prepend '0x' if missing before calling
  2. Fix the source data (config/env/CSV) to store full 42-char checksummed addresses
  3. Accept both '0x' and '0X' by lowercasing the prefix check in your own pre-validation

Example fix

// before
let addr = validate_address(&raw_address)?;
// after
let trimmed = raw_address.trim();
let normalized = if trimmed.starts_with("0x") {
    trimmed.to_string()
} else {
    format!("0x{trimmed}")
};
let addr = validate_address(&normalized)?;
Defensive patterns

Strategy: validation

Validate before calling

fn looks_like_address(s: &str) -> bool {
    let t = s.trim();
    t.len() == 42 && t.starts_with("0x") && t[2..].chars().all(|c| c.is_ascii_hexdigit())
}

Try / catch

let addr = validate_address(input)
    .map_err(|e| MyError::BadAddress { input: input.clone(), source: e })?;

Prevention

When it happens

Trigger: Calling validate_address with a string not starting with '0x' — e.g. a bare 40-char hex address, an address with a leading space, or an uppercase '0X' prefix (starts_with is case-sensitive).

Common situations: CSV/env/config token lists storing addresses without the 0x prefix; user-supplied addresses in subscribe commands; addresses copied from systems that strip the prefix.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/929ec5cecc907446. Report an issue: GitHub.