nautechsystems/nautilus_trader · error
quantity `{new_qty}` rounds to 0 ticks at size_precision {}
Error message
quantity `{new_qty}` rounds to 0 ticks at size_precision {} What it means
The modify's new quantity is converted to integer base-amount ticks at the instrument's size_precision. If the resulting tick value is 0 (quantity too small or below rounding granularity) the order would be invalid on Lighter, so the adapter rejects it up front.
Source
Thrown at crates/adapters/lighter/src/execution.rs:1980
derive_market_order_price_ticks(
trigger.as_decimal(),
is_buy,
price_precision,
slippage_bps,
)?
}
_ => {
let new_price = cmd.price.or(order.price()).ok_or_else(|| {
anyhow::anyhow!("modify_order requires a price (none on order or command)")
})?;
price_to_ticks(&new_price, price_precision)?
}
};
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,View on GitHub (pinned to 18893faf8b)
Solutions
- Increase the new quantity so it is at least one tick at the instrument's size_precision.
- Check the instrument definition's size_precision and size_increment; align strategy quantities to whole ticks.
- If the intent is to fully close, cancel the order instead of modifying quantity to ~0.
Example fix
// before let new_qty = Quantity::from(0.0004); // rounds to 0 ticks at precision 2 // after let new_qty = Quantity::new(Decimal::new(1, 2), 2); // 0.01 = 1 tick
Defensive patterns
Strategy: validation
Validate before calling
let ticks = (new_qty.as_decimal() * Decimal::from(10u64.pow(instrument.size_precision() as u32)))
.round()
.to_u64().unwrap_or(0);
if ticks == 0 { return Err("quantity below one tick".into()); } Try / catch
match client.modify_order(&cmd).await {
Err(e) if e.to_string().contains("rounds to 0 ticks") => cancel_order(&cmd.client_order_id).await?,
r => r?,
} Prevention
- Quantize all quantities to the instrument's size_increment before ordering.
- Reject reduce amounts smaller than one tick; cancel instead.
- Avoid f64 for quantity math — use Decimal.
When it happens
Trigger: prepare_signed_modify_order computes quantity_to_ticks(&new_qty, instrument.size_precision()) == 0 — the new quantity from cmd.quantity (or the order) rounds down to zero ticks, e.g. 0.0004 BTC at size_precision 2.
Common situations: Configured size_precision smaller than the quantity's decimals; very small reduce-only adjustments; position sizing computed in a different instrument's units; truncation from float-to-Decimal conversion losing precision.
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
- size decimals {decimals} exceeds maximum {MAX_DECIMALS}
- trigger_price `{new_trigger:?}` rounds to 0 ticks at precisi
- IncompleteOrderReports { reports, detail: detail.into() }
- AX requires whole contract quantities, was {}
- Order quantity must be at least 1 contract
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f8ecd81fa9286d33.
Report an issue: GitHub.