linera-io/linera-protocol · error

Invalid address length: {s}

Error message

Invalid address length: {s}

What it means

AccountOwner::from_str parses 0x-prefixed hex strings into one of three shapes: 64 hex chars → Address32 (a CryptoHash), 40 hex chars → Address20 (an EVM-style address), 2 hex chars → Reserved(u8). The 'Invalid address length' bail guards the 40-char branch when the decoded bytes are not exactly 20; since 40 hex characters always decode to 20 bytes, this arm is effectively a defensive unreachable check — malformed input more commonly surfaces as the adjacent 'Invalid address value' error or a hex decode error. Note this is a returned Err (anyhow::bail!), not a panic.

Source

Thrown at linera-base/src/identifiers.rs:1229

        };

        Ok(())
    }
}

impl std::str::FromStr for AccountOwner {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some(s) = s.strip_prefix("0x") {
            if s.len() == 64 {
                if let Ok(hash) = CryptoHash::from_str(s) {
                    return Ok(AccountOwner::Address32(hash));
                }
            } else if s.len() == 40 {
                let address = hex::decode(s)?;
                if address.len() != 20 {
                    anyhow::bail!("Invalid address length: {s}");
                }
                let address = <[u8; 20]>::try_from(address.as_slice()).unwrap();
                return Ok(AccountOwner::Address20(address));
            }
            if s.len() == 2 {
                let bytes = hex::decode(s)?;
                if bytes.len() == 1 {
                    let value = u8::from_be_bytes(bytes.try_into().expect("one byte"));
                    return Ok(AccountOwner::Reserved(value));
                }
            }
        }
        anyhow::bail!("Invalid address value: {s}");
    }
}

impl fmt::Display for ChainId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Use exactly 40 hex characters (20 bytes) with the 0x prefix for EVM-style Address20 owners
  2. Use 64 hex characters for 32-byte Address32 owners and 2 hex characters for Reserved values
  3. Validate owner strings in tests with AccountOwner::from_str before shipping configs or scripts

Example fix

// before
let owner: AccountOwner = "0x8da6bac7dc85b63b4326c28926a1c168786e3fc912".parse()?; // 41 hex chars

// after
let owner: AccountOwner = "0x8da6bac7dc85b63b4326c28926a1c168786e3fc9".parse()?; // 40 hex chars
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_account_owner(s: &str) -> bool {
    let Some(hex) = s.strip_prefix("0x") else { return false };
    match hex.len() {
        64 => hex.chars().all(|c| c.is_ascii_hexdigit()), // Address32
        40 => hex.chars().all(|c| c.is_ascii_hexdigit()), // Address20
        2 => hex.chars().all(|c| c.is_ascii_hexdigit()),  // Reserved(u8)
        _ => false,
    }
}
assert!(is_valid_account_owner(input), "not a valid AccountOwner: {input}");

Type guard

fn parse_account_owner(s: &str) -> Option<linera_base::identifiers::AccountOwner> {
    s.parse().ok()
}

Try / catch

match "0x8da...".parse::<AccountOwner>() {
    Ok(owner) => use_owner(owner),
    Err(e) => eprintln!("invalid AccountOwner (need 0x + 64/40/2 hex chars): {e:#}"),
}

Prevention

When it happens

Trigger: Parsing an owner string whose hex length doesn't match the 64/40/2 forms (falls through to 'Invalid address value'), contains non-hex characters (hex decode error), or — for this specific message — any hypothetical path where a 40-char string decodes to a length other than 20 bytes. Callers hit it via AccountOwner::from_str in CLI parsing, GraphQL input, or config deserialization.

Common situations: Copying Ethereum addresses with checksummed mixed-case (hex::decode accepts mixed case, so usually fine) or with missing/extra digits; passing a 20-byte address where a 32-byte owner (CryptoHash) is expected or vice versa; forgetting the 0x prefix; feeding a contract address where an AccountOwner string is wanted.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/03369bd7f455de8b. Report an issue: GitHub.