nautechsystems/nautilus_trader · error · anyhow::Error

Failed to create quantity from fill sz: {e}

Error message

Failed to create quantity from fill sz: {e}

What it means

Raised in parse_fill_report when Quantity::from_decimal_dp fails converting fill.sz into a domain Quantity at the instrument's size precision. The code takes fill.sz.abs(), so failure is not from sign but from unrepresentable magnitude, excessive scale, or overflow in the fixed-point QuantityRaw conversion. It indicates the venue-reported fill size can't be represented for this instrument.

Source

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

    }

    let trade_id = make_fill_trade_id(
        &fill.hash,
        fill.oid,
        fill.px,
        fill.sz,
        fill.time,
        fill.start_position,
    );
    let order_side = parse_fill_side(&fill.side);

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

    let last_px = Price::from_decimal_dp(fill.px, price_precision)
        .map_err(|e| anyhow::anyhow!("Failed to create price from fill px: {e}"))?;
    let last_qty = Quantity::from_decimal_dp(fill.sz.abs(), size_precision)
        .map_err(|e| anyhow::anyhow!("Failed to create quantity from fill sz: {e}"))?;

    let fee_amount = fill.fee;

    let fee_currency = resolve_fee_currency(fill.fee_token.as_str(), fee_amount, instrument)?;
    let commission = Money::from_decimal(fee_amount, fee_currency)
        .map_err(|e| anyhow::anyhow!("Failed to create commission from fee: {e}"))?;

    // Determine liquidity side based on 'crossed' flag
    let liquidity_side = if fill.crossed {
        LiquiditySide::Taker
    } else {
        LiquiditySide::Maker
    };

    let ts_event = UnixNanos::from(fill.time * 1_000_000);
    let report_id = UUID4::new();

    let report = FillReport::new(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the raw fill.sz and the instrument's size_precision; refresh instrument definitions if the venue changed lot size
  2. Verify the coin-to-instrument mapping so the correct size_precision is applied
  3. Normalize sz to the instrument precision before conversion or adjust the instrument definition
  4. Process fills individually so a single unrepresentable fill doesn't discard the entire response

Example fix

// before
let last_qty = Quantity::from_decimal_dp(fill.sz.abs(), size_precision)
    .map_err(|e| anyhow::anyhow!("Failed to create quantity from fill sz: {e}"))?;
// after
let last_qty = Quantity::from_decimal_dp(fill.sz.abs(), size_precision)
    .map_err(|e| anyhow::anyhow!("Failed to create quantity from fill sz {}: {e}", fill.sz))?;
Defensive patterns

Strategy: try-catch

Validate before calling

# Python: check fill size against instrument size precision
assert fill_sz > 0, "fill size must be positive"

Try / catch

try:
    fills = client.request_fill_reports(...)
except ValueError as e:
    if "fill sz" in str(e):
        log.warning("skipping fill with unrepresentable size: %s", e)
    else:
        raise

Prevention

When it happens

Trigger: Calling fill_reports_from_response for a fill whose sz has more decimal places than the instrument's size_precision, or whose scaled value exceeds QuantityRaw's range.

Common situations: Assets whose size decimals changed since instruments were loaded; extremely large fills near fixed-point limits; malformed/precision-heavy sz values from the venue API.

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