nautechsystems/nautilus_trader · error

Failed to parse '{field_name}' value '{value}' into Decimal:

Error message

Failed to parse '{field_name}' value '{value}' into Decimal: {e}

What it means

`parse_price` first converts the input string into a `rust_decimal::Decimal`; this error is thrown when `Decimal::from_str` fails, meaning the string is not a syntactically valid decimal number. The message names the field and the offending raw value plus the underlying parse error.

Source

Thrown at crates/adapters/dydx/src/common/parse.rs:120

    // Ensure we don't double-append when given a symbol already suffixed.
    if !base.ends_with("-PERP") {
        base.push_str("-PERP");
    }
    InstrumentId::new(Symbol::from_str_unchecked(&base), *DYDX_VENUE)
}

/// Parses a decimal string into a [`Price`].
///
/// Normalizes the decimal to strip trailing zeros and clamps precision to
/// [`FIXED_PRECISION`] to prevent panics from venue values with excessive
/// decimal places.
///
/// # Errors
///
/// Returns an error if the string cannot be parsed into a valid price.
pub fn parse_price(value: &str, field_name: &str) -> anyhow::Result<Price> {
    let decimal = Decimal::from_str(value).map_err(|e| {
        anyhow::anyhow!("Failed to parse '{field_name}' value '{value}' into Decimal: {e}")
    })?;
    let normalized = decimal.normalize();
    let precision = (normalized.scale() as u8).min(FIXED_PRECISION);
    Price::from_decimal_dp(normalized, precision).map_err(|e| {
        anyhow::anyhow!("Failed to parse '{field_name}' value '{value}' into Price: {e}")
    })
}

/// Parses a decimal string into a [`Quantity`].
///
/// Normalizes the decimal to strip trailing zeros and clamps precision to
/// [`FIXED_PRECISION`] to prevent panics from venue values with excessive
/// decimal places.
///
/// # Errors
///
/// Returns an error if the string cannot be parsed into a valid quantity.
pub fn parse_quantity(value: &str, field_name: &str) -> anyhow::Result<Quantity> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Validate/trim the input string and confirm it is a plain decimal like "100.5" before calling parse_price
  2. Normalize locale formatting (replace ',' with '.') before parsing
  3. Log the offending `{value}` at the call site to find the data source producing bad values
  4. For optional/empty inputs, handle emptiness before calling parse_price instead of passing ""

Example fix

// before
let price = parse_price(&raw, "entry_price")?;
// after
let raw = raw.trim();
if raw.is_empty() { anyhow::bail!("entry_price is empty"); }
let price = parse_price(raw, "entry_price")?;
Defensive patterns

Strategy: validation

Validate before calling

fn valid_price_str(s: &str) -> bool {
    let t = s.trim();
    !t.is_empty() && t.chars().all(|c| c.is_ascii_digit() || c == '.')
}

Type guard

fn parse_ok(s: &str) -> Option<rust_decimal::Decimal> { rust_decimal::Decimal::from_str(s.trim()).ok() }

Try / catch

let price = parse_price(raw, "entry_price")
    .map_err(|e| { log::error!("bad price input: {e}"); e })?;

Prevention

When it happens

Trigger: Calling `parse_price(value, field_name)` with a non-numeric string, empty string, embedded whitespace, locale-formatted numbers (comma decimal separator), or scientific notation variants Decimal rejects.

Common situations: Prices sourced from config files, environment variables, CSV/manual entry, or upstream API strings that are malformed or empty before reaching the parser.

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