nautechsystems/nautilus_trader · error

Invalid hex u64: {e}

Error message

Invalid hex u64: {e}

What it means

This error means a hex-encoded string (e.g. from an Ethereum RPC response) failed to parse as a u64. The helper strips an optional '0x' prefix and calls u64::from_str_radix base 16; any character that is not a valid hex digit, an empty string, or a value exceeding u64 range produces this error. It is thrown by parse_hex_u64, typically via extract_block_number.

Source

Thrown at crates/adapters/blockchain/src/rpc/log.rs:40

use nautilus_model::defi::rpc::RpcLog;

/// Decode hex string (with or without 0x prefix) to bytes.
///
/// # Errors
///
/// Returns an error if the hex string is invalid.
pub fn decode_hex(hex: &str) -> anyhow::Result<Vec<u8>> {
    hex::decode(hex.trim_start_matches("0x")).map_err(|e| anyhow::anyhow!("Invalid hex: {e}"))
}

/// Parse hex string to u64.
///
/// # Errors
///
/// Returns an error if the hex string cannot be parsed as u64.
pub fn parse_hex_u64(hex: &str) -> anyhow::Result<u64> {
    u64::from_str_radix(hex.trim_start_matches("0x"), 16)
        .map_err(|e| anyhow::anyhow!("Invalid hex u64: {e}"))
}

/// Parse hex string to u32.
///
/// # Errors
///
/// Returns an error if the hex string cannot be parsed as u32.
pub fn parse_hex_u32(hex: &str) -> anyhow::Result<u32> {
    u32::from_str_radix(hex.trim_start_matches("0x"), 16)
        .map_err(|e| anyhow::anyhow!("Invalid hex u32: {e}"))
}

/// Extract block number from RPC log.
///
/// # Errors
///
/// Returns an error if the block number is missing or cannot be parsed.
pub fn extract_block_number(log: &RpcLog) -> anyhow::Result<u64> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the offending string and confirm it is a valid hex quantity (optional 0x prefix, digits 0-9a-fA-F only, within u64 range).
  2. If the upstream field can be non-numeric (e.g. "pending"), check for that case before calling parse_hex_u64.
  3. Trim/normalize the input (trim whitespace, strip 0x) and validate with a regex before parsing.
  4. Increase the target type only if the value genuinely exceeds u64 range (use u128 or a big-int type).

Example fix

// before
let n = parse_hex_u64(log.block_number.as_deref().unwrap_or(""))?;
// after
let hex = log.block_number.as_deref().filter(|s| s.chars().all(|c| c.is_ascii_hexdigit()))
    .ok_or_else(|| anyhow::anyhow!("Missing block number"))?;
let n = parse_hex_u64(hex)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_hex_u64(s: &str) -> bool {
    let t = s.trim_start_matches("0x");
    !t.is_empty() && t.len() <= 16 && t.chars().all(|c| c.is_ascii_hexdigit())
}

Type guard

fn looks_like_hex_quantity(s: &str) -> bool {
    let t = s.trim_start_matches("0x");
    !t.is_empty() && t.chars().all(|c| c.is_ascii_hexdigit())
}

Try / catch

match parse_hex_u64(hex) {
    Ok(v) => v,
    Err(e) => { log::warn!("bad hex {hex}: {e}"); return Err(e); }
}

Prevention

When it happens

Trigger: Calling parse_hex_u64 with a string like "" (empty after stripping 0x), containing non-hex characters (e.g. "0x12g4"), whitespace embedded inside, or a number above u64::MAX (e.g. 20+ hex digits).

Common situations: Malformed or placeholder block-number fields from custom/nonstandard RPC nodes (some return "pending" or null-adjacent values), accidental double-encoding, or passing a full 32-byte topic hex where a short quantity hex was expected.

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/27a426bd4f9ea9fd. Report an issue: GitHub.