nautechsystems/nautilus_trader · error

market-buy amount must be positive

Error message

market-buy amount must be positive

What it means

adjust_market_buy_amount converts a market-buy notional into a fee-adjusted amount and first validates its inputs. The BUY amount must be strictly positive; a zero or negative amount is rejected with "market-buy amount must be positive".

Source

Thrown at crates/adapters/polymarket/src/execution/parse.rs:525

/// amount or balance is non-positive, a fee input is negative, arithmetic overflows,
/// or the adjusted amount truncates to zero.
pub fn adjust_market_buy_amount(
    amount: Decimal,
    user_pusd_balance: Decimal,
    price: Decimal,
    fee_rate: Decimal,
    fee_exponent: Decimal,
    builder_taker_fee_rate: Decimal,
) -> anyhow::Result<Decimal> {
    if price <= Decimal::ZERO || price >= Decimal::ONE {
        anyhow::bail!(
            "invalid market-buy price {price}: must satisfy 0 < price < 1 for fee adjustment",
        );
    }

    let platform_fee_rate = fee_curve_rate(fee_rate, price, fee_exponent)?;

    anyhow::ensure!(amount > Decimal::ZERO, "market-buy amount must be positive");
    anyhow::ensure!(
        user_pusd_balance > Decimal::ZERO,
        "market-buy balance must be positive"
    );
    anyhow::ensure!(
        builder_taker_fee_rate >= Decimal::ZERO,
        "builder fee rate must be non-negative"
    );
    let platform_fee = amount
        .checked_div(price)
        .and_then(|shares| shares.checked_mul(platform_fee_rate))
        .context("market-buy platform fee overflow")?;
    let builder_fee = amount
        .checked_mul(builder_taker_fee_rate)
        .context("market-buy builder fee overflow")?;
    let total_cost = amount
        .checked_add(platform_fee)
        .and_then(|cost| cost.checked_add(builder_fee))

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Guard the caller so a market BUY is only submitted when the computed amount is > 0; skip the order otherwise.
  2. Fix the upstream sizing/sign logic that produced a zero or negative notional.
  3. If using defaults in tests/benches, pass an explicit positive amount.

Example fix

// before
let amount = Decimal::ZERO;
adjust_market_buy_amount(amount, price, ...)?; // panics/errors
// after
if amount > Decimal::ZERO {
    adjust_market_buy_amount(amount, price, ...)?;
}
Defensive patterns

Strategy: validation

Validate before calling

if amount <= Decimal::ZERO { skip_order(); return; }

Type guard

fn is_positive_amount(amount: Decimal) -> bool { amount > Decimal::ZERO }

Try / catch

match adjust_market_buy_amount(amount, price, balance, fee_rate, exponent) {
    Ok(a) => submit(a),
    Err(e) if e.to_string().contains("amount must be positive") => tracing::warn!("zero-size market buy skipped"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling adjust_market_buy_amount (directly or via submit_market_order / benches) with amount <= 0 — e.g. a computed notional that rounded down to zero or a negative order quantity.

Common situations: Position sizers producing zero-size orders when capital is exhausted or filters leave no budget; sign errors when converting from a sell-side quantity; uninitialized/default Decimal amounts.

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