nautechsystems/nautilus_trader · error · anyhow::Error

Limit orders require a price

Error message

Limit orders require a price

What it means

When converting a Nautilus order to a Hyperliquid exchange request, limit-type orders must carry a limit price; the price is required to build Hyperliquid's limit px field. The adapter bails with this message when order.price() returns None for a Limit (or StopLimit's limit component), since it cannot derive a valid exchange price.

Source

Thrown at crates/adapters/hyperliquid/src/common/parse.rs:539

            raw.normalize()
        }
    } else if matches!(order_type, OrderType::Market) {
        Decimal::ZERO
    } else if matches!(
        order_type,
        OrderType::StopMarket | OrderType::MarketIfTouched
    ) {
        match order.trigger_price() {
            Some(tp) => {
                let base = tp.as_decimal().normalize();
                let derived = derive_limit_from_trigger(base, is_buy, slippage_bps);
                let sig_rounded = round_to_sig_figs(derived, 5);
                clamp_price_to_precision(sig_rounded, price_decimals, is_buy).normalize()
            }
            None => Decimal::ZERO,
        }
    } else {
        anyhow::bail!("Limit orders require a price")
    };

    let size_decimal = order.quantity().as_decimal().normalize();

    // Determine order kind based on order type
    let kind = match order_type {
        OrderType::Market => HyperliquidExchangeOrderKind::Limit {
            limit: HyperliquidExchangeLimitParams {
                tif: HyperliquidExchangeTif::Ioc,
            },
        },
        OrderType::Limit => {
            let tif =
                time_in_force_to_hyperliquid_tif(order.time_in_force(), order.is_post_only())?;
            HyperliquidExchangeOrderKind::Limit {
                limit: HyperliquidExchangeLimitParams { tif },
            }
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set a price on the limit order before submission: construct with order_factory.limit(instrument_id, side, quantity, price).
  2. Verify the order-building code path actually assigns the computed price (e.g. mid/market-adjusted price) before calling submit_order.
  3. Add a pre-submit assertion that limit orders have Some(price) so failures surface at the strategy layer with context.
  4. If a marketable order was intended, submit a Market order type instead of a priceless Limit.

Example fix

// before
let order = order_factory.limit(instrument_id, OrderSide::Buy, qty, None);
// after
let price = Price::from("42000.0");
let order = order_factory.limit(instrument_id, OrderSide::Buy, qty, Some(price));
Defensive patterns

Strategy: validation

Validate before calling

if order.order_type().is_limit() && order.price().is_none() {
    return Err(anyhow::anyhow!("limit order {} missing price", order.client_order_id()));
}
// run this before adapter.submit_order / modify_order

Try / catch

match adapter.submit_order(order).await {
    Err(e) if e.to_string().contains("Limit orders require a price") => {
        log::error!("order built without price; fix order factory call");
        Err(e)
    }
    r => r,
}

Prevention

When it happens

Trigger: Submitting or modifying a Limit order (via submit_order, submit_orders, order_request, modify_order) where the order was constructed without a price — e.g. order_factory.limit called without a price argument or with a null/None price propagated from upstream logic.

Common situations: Programmatic order construction where price is filled in later but the order is submitted before being set; ported strategy code from a venue where marketable-limit semantics allowed missing prices; deserialized orders from a message bus missing optional price fields.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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