nautechsystems/nautilus_trader · error
Polymarket market BUY amount {} pUSD truncates to zero at {L
Error message
Polymarket market BUY amount {} pUSD truncates to zero at {LOT_SIZE_SCALE} decimal places What it means
For market BUY orders on Polymarket, amount is denominated in pUSD; it must round to at least one lot (0.01 pUSD) when truncated to LOT_SIZE_SCALE. build_market_order rejects amounts that truncate to zero, because a zero maker amount would produce an invalid order. This protects against tiny/dust buy amounts being submitted to the CLOB.
Source
Thrown at crates/adapters/polymarket/src/execution/order_builder.rs:206
/// Builds and signs a market order for submission.
///
/// `amount` semantics differ by side:
/// - BUY: `amount` is pUSD to spend
/// - SELL: `amount` is shares to sell
///
/// Market orders never set an expiration.
pub fn build_market_order(
&self,
token_id: &str,
side: PolymarketOrderSide,
price: Decimal,
amount: Decimal,
neg_risk: bool,
tick_decimals: u32,
) -> anyhow::Result<PolymarketOrder> {
if side == PolymarketOrderSide::Buy && amount.trunc_with_scale(LOT_SIZE_SCALE).is_zero() {
anyhow::bail!(
"Polymarket market BUY amount {} pUSD truncates to zero at {LOT_SIZE_SCALE} decimal places",
amount.normalize(),
);
}
let (maker_amount, taker_amount) =
compute_market_maker_taker_amounts(price, amount, side, tick_decimals);
self.build_and_sign(token_id, side, maker_amount, taker_amount, "0", neg_risk)
}
/// Computes the Polymarket order ID for a signed CLOB V2 order.
pub fn expected_order_id(
&self,
order: &PolymarketOrder,
neg_risk: bool,
) -> anyhow::Result<VenueOrderId> {
let hash = order_hash(order, neg_risk)
.map_err(|e| anyhow::anyhow!("Failed to derive order hash: {e}"))?;View on GitHub (pinned to 18893faf8b)
Solutions
- Increase the market BUY amount to at least one lot (0.01 pUSD, practically the exchange minimum)
- Clamp or skip orders whose computed amount is below the minimum notional before calling submit
- Check upstream sizing/rounding logic that produced the sub-lot amount
- If amounts are intentionally tiny, route them through limit orders or batch them
Example fix
// before
let amount = expected_notional * (1.0 - fee_buffer); // may fall below 0.01
client.submit_market_order(instrument, OrderSide::Buy, amount, ...).await?;
// after
let amount = expected_notional * (1.0 - fee_buffer);
if amount.trunc_with_scale(2) >= Decimal::from_str_exact("0.01")? {
client.submit_market_order(instrument, OrderSide::Buy, amount, ...).await?;
} else {
log::debug!("skip market BUY: amount {amount} below minimum lot");
} Defensive patterns
Strategy: validation
Validate before calling
use rust_decimal::Decimal;
const LOT_SIZE_SCALE: u32 = 2;
fn market_buy_amount_ok(amount: Decimal) -> bool {
!amount.trunc_with_scale(LOT_SIZE_SCALE).is_zero()
}
// call before submit
if !market_buy_amount_ok(amount) {
// skip or bump the order size
} Try / catch
match client.submit_market_order(instrument, OrderSide::Buy, amount, ...).await {
Err(e) if e.to_string().contains("truncates to zero") => {
warn!("market BUY amount {amount} below minimum lot; order skipped");
}
Err(e) => return Err(e),
Ok(_) => {},
} Prevention
- Enforce a minimum notional in strategy sizing logic before emitting orders
- Round position sizes up to the lot scale instead of truncating for buys
- Check fee/rounding adjustments don't shrink amounts below the minimum
- Add unit tests for dust-sized order amounts
When it happens
Trigger: Calling build_market_order (via submit_market_order) with side=Buy and an amount in pUSD whose value truncated to 2 decimal places equals zero (e.g. 0.004 pUSD).
Common situations: Strategy computes a position size smaller than the minimum notional; rounding or fee-adjustment shrinks the order amount below 0.01; unit tests with sub-lot amounts; currency conversion leaving fractional dust.
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
- Tick size {tick_size} must be positive
- Gamma {scope} filter '{key}' must be a decimal number: {e}
- trade quantity must be positive
- event_slug_builder.interval_mins must be positive
- event_slug_builder.periods must be positive
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/fc3525fed7a18fb4.
Report an issue: GitHub.