nautechsystems/nautilus_trader · error · anyhow::Error

Failed to create trigger price: {e}

Error message

Failed to create trigger price: {e}

What it means

Raised in parse_order_status_report_from_basic for conditional (trigger/stop) orders when Price::from_decimal_dp fails converting order.trigger_px into a domain Price at the instrument's price precision. Trigger prices from Hyperliquid must be representable in the fixed-point Price type; failures mean the value is negative, out of raw range, overflows during scaling, or uses a precision the Price type can't hold.

Source

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

    if let Some(reason) = status.rejection_reason() {
        report = report.with_cancel_reason(reason.to_string());
    }

    // Only set price for non-filled orders. For filled orders, the limit price is not
    // the execution price, and setting it would cause bogus inferred fills to be created
    // during reconciliation. Real fills arrive via the userEvents WebSocket channel.
    if !matches!(
        order_status,
        OrderStatus::Filled | OrderStatus::PartiallyFilled
    ) {
        let price = Price::from_decimal_dp(order.limit_px, price_precision)
            .map_err(|e| anyhow::anyhow!("Failed to create price from limit_px: {e}"))?;
        report = report.with_price(price);
    }

    if is_conditional && let Some(trigger_px) = order.trigger_px {
        let trigger_price = Price::from_decimal_dp(trigger_px, price_precision)
            .map_err(|e| anyhow::anyhow!("Failed to create trigger price: {e}"))?;
        report = report
            .with_trigger_price(trigger_price)
            .with_trigger_type(TriggerType::Default);
    }

    Ok(report)
}

/// Parses a `recentTrades` info entry into a [`TradeTick`].
///
/// Mirrors the field mapping of the WebSocket trade parser
/// [`parse_ws_trade_tick`](crate::websocket::parse::parse_ws_trade_tick): both the
/// `trades` channel and the `recentTrades` endpoint carry the same
/// `px`/`sz`/`side`/`time`/`tid` fields. For this historical snapshot `ts_init` is
/// set to the trade's `ts_event` (venue time), matching the other request
/// converters so the data engine's window trimming keeps bounded requests.
///
/// # Errors

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the raw trigger_px value in the response; confirm it is a positive decimal within the instrument's price range
  2. Re-fetch/refresh instrument definitions so price_precision matches current venue tick rules
  3. Normalize trigger_px to the instrument precision before conversion, or update the instrument definition precision
  4. Catch per-order and skip/mark-degraded conditional orders instead of aborting the whole reconciliation sweep

Example fix

// before
let trigger_price = Price::from_decimal_dp(trigger_px, price_precision)
    .map_err(|e| anyhow::anyhow!("Failed to create trigger price: {e}"))?;
// after
let trigger_price = Price::from_decimal_dp(trigger_px, price_precision)
    .map_err(|e| anyhow::anyhow!("Failed to create trigger price from {trigger_px}: {e}"))?;
Defensive patterns

Strategy: validation

Validate before calling

# Python: validate trigger price before requesting conditional order status
if trigger_px <= 0:
    raise ValueError(f"invalid trigger_px {trigger_px}")

Try / catch

try:
    report = client.request_order_status_report(instrument_id, client_order_id)
except ValueError as e:
    if "trigger price" in str(e):
        log.warning("bad trigger_px for conditional order: %s", e)
    else:
        raise

Prevention

When it happens

Trigger: Requesting an order status report for a conditional order (stop-loss/take-under trigger order) whose trigger_px is negative, extremely large, or has more decimal places than the instrument's price_precision allows.

Common situations: Liquidation/stop orders with extreme trigger prices during volatile markets; instrument definitions fetched with wrong precision; API format changes to trigger_px.

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