nautechsystems/nautilus_trader · error

Failed to parse `ct_mult` '{}' for {}: {e}

Error message

Failed to parse `ct_mult` '{}' for {}: {e}

What it means

parse_multiplier_product computes the contract multiplier from ct_mult and ct_val. When ct_mult is non-empty but not a valid decimal string, Decimal::from_str fails and this error is raised naming the value and inst_id.

Source

Thrown at crates/adapters/okx/src/common/parse.rs:1903

    margin_maint: Option<Decimal>,
    maker_fee: Option<Decimal>,
    taker_fee: Option<Decimal>,
}

/// Parses the multiplier as the product of ct_mult and ct_val.
///
/// For SPOT instruments where both fields are empty, returns None.
/// For derivatives, multiplies the two fields to get the final multiplier.
fn parse_multiplier_product(definition: &OKXInstrument) -> anyhow::Result<Option<Quantity>> {
    if definition.ct_mult.is_empty() && definition.ct_val.is_empty() {
        return Ok(None);
    }

    let mult_value = if definition.ct_mult.is_empty() {
        Decimal::ONE
    } else {
        Decimal::from_str(&definition.ct_mult).map_err(|e| {
            anyhow::anyhow!(
                "Failed to parse `ct_mult` '{}' for {}: {e}",
                definition.ct_mult,
                definition.inst_id
            )
        })?
    };

    let val_value = if definition.ct_val.is_empty() {
        Decimal::ONE
    } else {
        Decimal::from_str(&definition.ct_val).map_err(|e| {
            anyhow::anyhow!(
                "Failed to parse `ct_val` '{}' for {}: {e}",
                definition.ct_val,
                definition.inst_id
            )
        })?
    };

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect ct_mult in the failing definition; it must be a plain decimal string or empty
  2. Re-fetch instrument definitions from the OKX /public/instruments endpoint
  3. Strip units/formatting from ct_mult before parsing
  4. If ct_mult is unknown, leave it empty so the parser defaults it to Decimal::ONE

Example fix

// before
"ctMult": "2x"
// after
"ctMult": "2"
Defensive patterns

Strategy: validation

Validate before calling

fn ct_mult_valid(def: &OKXInstrument) -> bool {
    def.ct_mult.is_empty() || def.ct_mult.parse::<rust_decimal::Decimal>().is_ok()
}

Try / catch

let multiplier = match parse_multiplier_product(&definition) {
    Ok(m) => m,
    Err(e) => { tracing::error!("contract multiplier parse failed: {e:#}"); return; }
};

Prevention

When it happens

Trigger: Calling any of parse_swap_instrument / parse_futures_instrument / parse_option_instrument / parse_specific_fields on an OKX instrument definition whose ct_mult field is populated with a non-decimal string.

Common situations: Placeholder or corrupt values in cached instrument JSON; OKX payload schema drift; manual fixtures with wrong values (e.g. '1x' instead of '1').

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