nautechsystems/nautilus_trader · error
trigger_price `{new_trigger:?}` rounds to 0 ticks at precisi
Error message
trigger_price `{new_trigger:?}` rounds to 0 ticks at precision {price_precision} What it means
For trigger-type orders (StopMarket, StopLimit, MarketIfTouched, LimitIfTouched) the trigger price must convert to a positive tick count at the price_precision. A trigger of zero or one so small it rounds to 0 ticks is invalid, so the adapter ensures trigger_price_ticks > 0 before validating amounts.
Source
Thrown at crates/adapters/lighter/src/execution.rs:1997
let base_amount = quantity_to_ticks(&new_qty, instrument.size_precision())?;
anyhow::ensure!(
base_amount > 0,
"quantity `{new_qty}` rounds to 0 ticks at size_precision {}",
instrument.size_precision(),
);
let trigger_price_ticks = match new_trigger {
Some(trigger) if trigger.raw != 0 => price_to_ticks(&trigger, price_precision)?,
_ => 0,
};
if matches!(
order.order_type(),
OrderType::StopMarket
| OrderType::StopLimit
| OrderType::MarketIfTouched
| OrderType::LimitIfTouched
) {
anyhow::ensure!(
trigger_price_ticks > 0,
"trigger_price `{new_trigger:?}` rounds to 0 ticks at precision {price_precision}",
);
}
validate_order_amount(&instrument, new_qty, price_ticks, price_precision)?;
let ReservedTxContext {
context,
send_reservation,
} = self.build_tx_context(credential)?;
let captured_nonce = context.nonce;
let captured_api_key_index = context.api_key_index;
let mut rollback_guard =
TxDispatchGuard::new(self.dispatch.clone(), credential, None, captured_nonce);
let tx = ModifyOrderTxInfo {View on GitHub (pinned to 18893faf8b)
Solutions
- Supply a real trigger_price above one tick at price_precision for trigger order types.
- Verify the instrument's price_precision/price_increment and express the trigger in those units.
- Guard the command: reject trigger prices <= price_increment before calling modify.
Example fix
// before
let cmd = ModifyOrder { trigger_price: Some(Price::from(0)), ..cmd };
// after
if trigger.as_decimal() <= instrument.price_increment().as_decimal() {
return Err(anyhow!("trigger {} below one tick", trigger));
}
let cmd = ModifyOrder { trigger_price: Some(trigger), ..cmd }; Defensive patterns
Strategy: validation
Validate before calling
if let Some(t) = cmd.trigger_price {
if t.as_decimal() < instrument.price_increment().as_decimal() {
return Err("trigger_price below one tick".into());
}
} Try / catch
if let Err(e) = client.modify_order(&cmd).await {
if e.to_string().contains("trigger_price") && e.to_string().contains("0 ticks") {
// fix trigger or cancel/re-place with a valid trigger
}
} Prevention
- Never allow placeholder (0) trigger prices into modify commands.
- Validate trigger >= price_increment for all trigger order types.
- Re-derive triggers from instrument precision when switching markets.
When it happens
Trigger: prepare_signed_modify_order computes trigger_price_ticks from new_trigger, and for one of the four trigger order types the value is <= 0 — e.g. trigger_price of 0 on the command, or an extremely low price below one tick at the instrument's price precision.
Common situations: Uninitialized/placeholder trigger (0) passed in a ModifyOrder; price-precision mismatch after switching markets (e.g. tick size 0.01 vs trigger 0.004); Decimal parsing yielding 0 from a malformed string.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- quantity `{new_qty}` rounds to 0 ticks at size_precision {}
- IncompleteOrderReports { reports, detail: detail.into() }
- invalid price for '{key}': '{s}', expected a finite non-nega
- Stop market orders require a trigger price
- Stop limit orders require a trigger price
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b03f959c16f0e82b.
Report an issue: GitHub.