{"record":{"id":"929ec5cecc907446","repo":"nautechsystems/nautilus_trader","slug":"ethereum-address-must-start-with-0x-address","errorCode":null,"errorMessage":"Ethereum address must start with '0x': {address}","messagePattern":"Ethereum address must start with '0x': (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/validation.rs","lineNumber":38,"sourceCode":"//! blockchain identifiers.\n\nuse std::str::FromStr;\n\nuse alloy_primitives::Address;\n\n/// Validates an Ethereum address format, checksum, and returns the parsed address.\n///\n/// # Errors\n///\n/// This function returns an error if:\n/// - The address does not start with the `0x` prefix.\n/// - The address has invalid length (must be 42 characters including `0x`).\n/// - The address contains invalid hexadecimal characters.\n/// - The address has an incorrect checksum (for checksummed addresses).\npub fn validate_address(address: &str) -> anyhow::Result<Address> {\n    // Check if the address starts with \"0x\"\n    if !address.starts_with(\"0x\") {\n        anyhow::bail!(\"Ethereum address must start with '0x': {address}\");\n    }\n\n    // Check if the address is valid\n    let parsed_address = Address::from_str(address)\n        .map_err(|e| anyhow::anyhow!(\"Blockchain address '{address}' is incorrect: {e}\"))?;\n\n    // Check if checksum is valid\n    Address::parse_checksummed(address, None)\n        .map_err(|_| anyhow::anyhow!(\"Blockchain address '{address}' has incorrect checksum\"))?;\n\n    Ok(parsed_address)\n}\n\n#[cfg(test)]\nmod tests {\n    use rstest::rstest;\n\n    use super::*;","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/validation.rs#L20-L56","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Normalize the input: trim whitespace and prepend '0x' if missing before calling","Fix the source data (config/env/CSV) to store full 42-char checksummed addresses","Accept both '0x' and '0X' by lowercasing the prefix check in your own pre-validation"],"exampleFix":"// before\nlet addr = validate_address(&raw_address)?;\n// after\nlet trimmed = raw_address.trim();\nlet normalized = if trimmed.starts_with(\"0x\") {\n    trimmed.to_string()\n} else {\n    format!(\"0x{trimmed}\")\n};\nlet addr = validate_address(&normalized)?;","handlingStrategy":"validation","validationCode":"fn looks_like_address(s: &str) -> bool {\n    let t = s.trim();\n    t.len() == 42 && t.starts_with(\"0x\") && t[2..].chars().all(|c| c.is_ascii_hexdigit())\n}","typeGuard":null,"tryCatchPattern":"let addr = validate_address(input)\n    .map_err(|e| MyError::BadAddress { input: input.clone(), source: e })?;","preventionTips":["Store addresses as full 42-char checksummed strings in config/env","Trim and normalize prefix before validation","Validate token lists at load time, not at use time"],"tags":["rust","validation","address","ethereum"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}