nautechsystems/nautilus_trader · error
Polymarket collateral-sized limit BUY amount {} pUSD cannot
Error message
Polymarket collateral-sized limit BUY amount {} pUSD cannot preserve limit price {} after venue quantization What it means
After the venue quantizes maker_amount and taker_amount to LOT_SIZE_SCALE decimals, the invariant taker_amount * price == maker_amount must still hold exactly, otherwise the effective fill price would silently differ from the requested limit price. The builder throws when quantization breaks this equality.
Source
Thrown at crates/adapters/polymarket/src/execution/order_builder.rs:172
tick_decimals: u32,
) -> anyhow::Result<PolymarketOrder> {
anyhow::ensure!(
price > Decimal::ZERO,
"Polymarket collateral-sized limit BUY price must be positive"
);
let (maker_amount, taker_amount) =
compute_quote_buy_maker_taker_amounts(price, amount, tick_decimals);
anyhow::ensure!(
maker_amount > Decimal::ZERO,
"Polymarket collateral-sized limit BUY amount {} pUSD truncates to zero at {LOT_SIZE_SCALE} decimal places",
amount.normalize(),
);
anyhow::ensure!(
taker_amount > Decimal::ZERO,
"Polymarket collateral-sized limit BUY derives a zero share quantity"
);
anyhow::ensure!(
taker_amount * price == maker_amount,
"Polymarket collateral-sized limit BUY amount {} pUSD cannot preserve limit price {} after venue quantization",
amount.normalize(),
price.normalize(),
);
self.build_and_sign(
token_id,
PolymarketOrderSide::Buy,
maker_amount,
taker_amount,
expiration,
neg_risk,
)
}
/// Builds and signs a market order for submission.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Adjust the collateral amount so that after quantization, taker_amount * price equals maker_amount exactly (quantize amount to price-compatible increments).
- Slightly round the amount up/down to the nearest value that preserves the limit price post-quantization before calling build_limit_order_from_collateral.
- Confirm price and tick_decimals match the venue market; a wrong tick_decimals changes the quantization grid.
Example fix
// before let amount = Decimal::new(10037, 2); // 100.37 pUSD at price 0.333 -> quantization breaks invariant // after let amount = (price * shares_wanted).round_dp(LOT_SIZE_SCALE); // choose amount exactly = price * quantized shares
Defensive patterns
Strategy: validation
Validate before calling
let maker = (amount * price_unit_factor).round_dp(lot_size_scale);
let taker = (amount / price).round_dp(lot_size_scale);
if taker * price != maker { /* re-quantize amount */ } Type guard
fn preserves_limit_price(amount: Decimal, price: Decimal, dp: u32) -> bool {
let maker = (amount).round_dp(dp);
let taker = (amount / price).round_dp(dp);
taker * price == maker
} Prevention
- Derive amount as price * quantized_shares instead of an arbitrary decimal notional.
- Re-quantize the amount to a price-compatible increment before building.
- Test with prices that have non-terminating decimal expansions (e.g. 0.333).
When it happens
Trigger: build_limit_order_from_collateral with an amount/price combination whose rounded maker and taker amounts no longer multiply back to the original price — typical when amount is not an exact multiple of price at the venue's quantization.
Common situations: Collateral budgets that are arbitrary decimals (e.g. 100.37 pUSD) combined with prices like 0.333; tests asserting exact price preservation; venue tick-decimal changes making previously valid amounts invalid.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Polymarket collateral-sized limit BUY derives a zero share q
- Expected 2 token IDs, received {}
- Expected 2 outcomes, received {}
- RTDS WebSocket client unavailable after reconcile
- WS message receiver not available after connect
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b5d6c1b958ff102e.
Report an issue: GitHub.