nautechsystems/nautilus_trader · error · anyhow::Error

Failed to create quantity from filled_sz: {e}

Error message

Failed to create quantity from filled_sz: {e}

What it means

This error is raised in parse_order_status_report_from_basic when Quantity::from_decimal_dp fails while converting the computed filled size (orig_sz - sz, both absolute) into a domain Quantity at the instrument's size precision. Quantity::from_decimal_dp rejects negative values, values exceeding the fixed-point raw range, and conversion overflow, so it fails when the exchange reports an inconsistent pair (sz > orig_sz) or absurdly large/precision-heavy sizes. The anyhow context wraps the underlying CorrectnessError for the caller.

Source

Thrown at crates/adapters/hyperliquid/src/http/parse.rs:970

        OrderType::Limit
    };

    let time_in_force = order
        .tif
        .map_or(TimeInForce::Gtc, hyperliquid_time_in_force_to_nautilus);
    let order_status = OrderStatus::from(*status);

    let price_precision = instrument.price_precision();
    let size_precision = instrument.size_precision();

    let orig_sz = order.orig_sz;
    let current_sz = order.sz;

    let quantity = Quantity::from_decimal_dp(orig_sz.abs(), size_precision)
        .map_err(|e| anyhow::anyhow!("Failed to create quantity from orig_sz: {e}"))?;
    let filled_sz = orig_sz.abs() - current_sz.abs();
    let filled_qty = Quantity::from_decimal_dp(filled_sz, size_precision)
        .map_err(|e| anyhow::anyhow!("Failed to create quantity from filled_sz: {e}"))?;

    let ts_accepted = UnixNanos::from(order.timestamp * 1_000_000);
    let ts_last = ts_accepted;
    let report_id = UUID4::new();

    let mut report = OrderStatusReport::new(
        account_id,
        instrument_id,
        None, // client_order_id - will be set if present
        venue_order_id,
        order_side.into(),
        order_type,
        time_in_force,
        order_status,
        quantity,
        filled_qty,
        ts_accepted,
        ts_last,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the raw response fields orig_sz and sz from Hyperliquid; verify sz <= orig_sz and both parse as valid non-negative decimals
  2. Verify the instrument definition (size_precision from the parsed Instrument) matches the venue's asset decimals; re-fetch instrument definitions if stale
  3. Log the full order payload and the inner CorrectnessError to distinguish negative-value vs overflow failure and report a data-quality issue upstream if the exchange data is inconsistent
  4. If handling historical/reconciliation data, guard the parse call and skip (or mark degraded) the offending order rather than failing the whole batch

Example fix

// before
let filled_sz = orig_sz.abs() - current_sz.abs();
let filled_qty = Quantity::from_decimal_dp(filled_sz, size_precision)
    .map_err(|e| anyhow::anyhow!("Failed to create quantity from filled_sz: {e}"))?;
// after
let filled_sz = orig_sz.abs() - current_sz.abs();
anyhow::ensure!(filled_sz >= Decimal::ZERO, "Negative filled_sz {filled_sz} (orig_sz={orig_sz}, sz={current_sz})");
let filled_qty = Quantity::from_decimal_dp(filled_sz, size_precision)
    .map_err(|e| anyhow::anyhow!("Failed to create quantity from filled_sz: {e}"))?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: before requesting order status, sanity-check reported sizes
if order.sz.abs() > order.orig_sz.abs() {
    // inconsistent data; skip or log
}
anyhow::ensure!(orig_sz.abs() >= current_sz.abs(), "sz exceeds orig_sz");

Type guard

fn is_valid_filled_size(orig_sz: rust_decimal::Decimal, sz: rust_decimal::Decimal) -> bool {
    orig_sz.abs() >= sz.abs() && orig_sz.abs() <= rust_decimal::Decimal::from_i128_with_scale(1, 0)
        || orig_sz.abs() >= sz.abs()
}

Try / catch

match parse_order_status_report_from_basic(...) {
    Ok(report) => emit(report),
    Err(e) if e.to_string().contains("filled_sz") => log::warn!("skipping order with bad filled size: {e}"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling request_order_status_report(s), request_order_status_report_by_client_order_id, historical_order_status_reports_from_response, or parsing a WS order update where the Hyperliquid order response yields filled_sz = |orig_sz| - |sz| that is negative (sz > orig_sz in exchange data), or whose mantissa scale/overflow cannot round-trip into QuantityRaw at the instrument's size_precision.

Common situations: Exchange data anomalies or API changes returning orig_sz/sz inconsistently (e.g. after partial-cancel events or during reconciliation of old orders); instruments defined with a size_precision that makes banker's rounding overflow; reconciling orders for many dexes where stale/corrupted records appear.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/359b21c704ed0c86. Report an issue: GitHub.