nautechsystems/nautilus_trader · error

Invalid receipt log quantity

Error message

Invalid receipt log quantity

What it means

parse_optional_quantity converts an optional string field of a receipt log into a u64, interpreting the value as a base-16 number (an optional 0x prefix is stripped first). If the string is not valid hexadecimal or the number overflows u64, the error 'Invalid receipt log quantity' is returned. It guards numeric log fields (indices, counts, block numbers) from malformed input.

Source

Thrown at crates/adapters/blockchain/src/rpc/verification.rs:1954

        self.effective_gas_price.write_normalized(output);
        self.transaction_index.write_normalized(output);
        self.status.write_normalized(output);
        self.logs.write_normalized(output);
    }
}

fn parse_optional_hash(value: Option<&str>) -> anyhow::Result<Option<B256>> {
    value
        .map(|value| B256::from_str(value).map_err(|_| anyhow::anyhow!("Invalid receipt log hash")))
        .transpose()
}

fn parse_optional_quantity(value: Option<&str>) -> anyhow::Result<Option<u64>> {
    value
        .map(|value| {
            let value = value.strip_prefix("0x").unwrap_or(value);
            u64::from_str_radix(value, 16)
                .map_err(|_| anyhow::anyhow!("Invalid receipt log quantity"))
        })
        .transpose()
}

#[cfg(test)]
mod tests {
    use alloy::{
        primitives::{
            U256, address,
            aliases::{U24, U160},
            b256,
        },
        sol_types::SolValue,
    };
    use rstest::rstest;

    use super::*;
    use crate::rpc::http::tests::mock::{MockRpcState, start_mock_rpc_server};

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the value is stored as a hex string (optionally 0x-prefixed) before parsing
  2. Trim whitespace and normalize the 0x prefix on the source data
  3. If values can exceed u64, widen the parser to u128/U256 instead of u64
  4. Validate the string with a hex regex before calling parse_optional_quantity

Example fix

// before
parse_optional_quantity(Some("123"))?; // decimal digits -> fails hex radix parse? actually valid hex too, but "12z" fails
// after
let raw = log.quantity.trim();
let normalized = if let Some(stripped) = raw.strip_prefix("0x") { stripped.to_lowercase() } else { raw.to_lowercase() };
assert!(normalized.chars().all(|c| c.is_ascii_hexdigit()));
parse_optional_quantity(Some(&raw))?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_hex_u64(s: &str) -> bool {
    let h = s.trim().trim_start_matches("0x");
    !h.is_empty() && h.chars().all(|c| c.is_ascii_hexdigit()) && u64::from_str_radix(h, 16).is_ok()
}

Type guard

fn as_u64_quantity(value: Option<&str>) -> Option<u64> {
    value.and_then(|v| {
        let h = v.strip_prefix("0x").unwrap_or(v);
        u64::from_str_radix(h, 16).ok()
    })
}

Try / catch

match parse_optional_quantity(field) {
    Ok(q) => use_quantity(q),
    Err(e) => { warn!("bad quantity: {e}"); treat_as_missing(); }
}

Prevention

When it happens

Trigger: A receipt-log quantity string containing decimal digits beyond a-f, sign characters, whitespace, a double 0x0x prefix, or a value exceeding u64::MAX (e.g. a 256-bit integer) passed to the log parsing path (verification.rs:~1954).

Common situations: Storing decimal values in a field expected to be hex; negative numbers ('-1'); very large EVM uint256 values that cannot fit u64; values copied with stray whitespace or surrounding quotes.

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/0ee0d38ecd26b861. Report an issue: GitHub.