nautechsystems/nautilus_trader · error

{} orders do not have a LIMIT price

Error message

{} orders do not have a LIMIT price

What it means

modify_orders was given a price argument for an order whose type is not in LIMIT_ORDER_TYPES. Only limit-type orders (LIMIT, LIMIT_IF_TOUCHED, etc.) carry a limit price, so passing price for a MARKET or STOP_MARKET order bails naming the order type.

Source

Thrown at crates/trading/src/strategy/mod.rs:373

        let params = params.filter(|params| !params.is_empty());

        // TODO: Snapshot the order from the cache. See `cancel_order` for the rationale.
        let order = StrategyNative::strategy_core_mut(self)
            .cache_rc()
            .borrow()
            .try_order_owned(&client_order_id)
            .map_err(|e| anyhow::anyhow!("Cannot modify order: {e}"))?;

        let mut updating = false;

        if quantity.is_some_and(|q| q != order.quantity() || order.is_pending_update()) {
            updating = true;
        }

        if let Some(price) = price {
            if !LIMIT_ORDER_TYPES.contains(&order.order_type()) {
                anyhow::bail!("{} orders do not have a LIMIT price", order.order_type());
            }

            if Some(price) != order.price() {
                updating = true;
            }
        }

        if let Some(trigger_price) = trigger_price {
            if !STOP_ORDER_TYPES.contains(&order.order_type()) {
                anyhow::bail!(
                    "{} orders do not have a STOP trigger price",
                    order.order_type()
                );
            }

            if Some(trigger_price) != order.trigger_price() {
                updating = true;
            }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Only pass price for LIMIT-type orders; use trigger_price for stop orders.
  2. Branch on order.order_type() (or self.cache order type) before supplying price.
  3. Pass None for price when modifying non-limit orders and only amend quantity or other applicable fields.

Example fix

// before
self.modify_order(order, price=new_price)  # order is STOP_MARKET

// after
if order.order_type in (OrderType.LIMIT, OrderType.LIMIT_IF_TOUCHED):
    self.modify_order(order, price=new_price)
else:
    self.modify_order(order, trigger_price=new_trigger)
Defensive patterns

Strategy: type-guard

Validate before calling

LIMIT_TYPES = {OrderType.LIMIT, OrderType.LIMIT_IF_TOUCHED}
if price is not None and order.order_type not in LIMIT_TYPES:
    raise TypeError(f"{order.order_type} orders do not accept a limit price")

Type guard

def accepts_limit_price(order) -> bool:
    return order.order_type in {OrderType.LIMIT, OrderType.LIMIT_IF_TOUCHED}

Try / catch

try:
    self.modify_order(order, price=new_price)
except RuntimeError as e:
    if "do not have a LIMIT price" in str(e):
        self.log.error("use trigger_price for stop-type orders")
    else:
        raise

Prevention

When it happens

Trigger: Calling strategy.modify_order/modify_orders with price=Some(...) on a MARKET, MARKET_TO_LIMIT-unsupported, STOP_MARKET, or TRAILING_STOP_MARKET order.

Common situations: A bulk modify loop that forwards the same price kwarg to every open order regardless of type; assuming an order is a limit after a strategy refactor; amending stop orders intending to change the trigger but passing price.

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