nautechsystems/nautilus_trader · error
fee quantity must be non-negative
Error message
fee quantity must be non-negative
What it means
compute_commission calculates the venue commission for a fill and requires the fill size (quantity) to be non-negative. A negative size would invert fee math, so the function rejects it up front with "fee quantity must be non-negative".
Source
Thrown at crates/adapters/polymarket/src/execution/parse.rs:594
/// the post-trade rate that actually applied; under V2 the fee is no longer carried
/// in the signed order, so we compute commissions from the instrument's fee schedule
/// rather than reading any cap off the order body.
///
/// # Errors
///
/// Returns an error for negative rates, exponents, or sizes, prices outside `[0, 1]`,
/// or a calculation that cannot be represented.
///
/// # References
/// <https://docs.polymarket.com/trading/fees>
pub fn compute_commission(
fee_rate: Decimal,
fee_exponent: Decimal,
size: Decimal,
price: Decimal,
liquidity_side: LiquiditySide,
) -> anyhow::Result<Decimal> {
anyhow::ensure!(size >= Decimal::ZERO, "fee quantity must be non-negative");
let rate = fee_curve_rate(fee_rate, price, fee_exponent)?;
if liquidity_side != LiquiditySide::Taker {
return Ok(Decimal::ZERO);
}
let commission = size
.checked_mul(rate)
.context("commission calculation overflow")?;
Ok(commission.round_dp(5))
}
fn fee_curve_rate(
fee_rate: Decimal,
price: Decimal,
fee_exponent: Decimal,
) -> anyhow::Result<Decimal> {
anyhow::ensure!(fee_rate >= Decimal::ZERO, "fee rate must be non-negative");
anyhow::ensure!(View on GitHub (pinned to 18893faf8b)
Solutions
- Sanitize the fill size before computing commission (take the absolute value or reject negative-size reports at parse time).
- Fix the upstream fill parsing/netting code that produced a negative quantity.
- If the negative value indicates an invalid venue payload, drop the fill report and log the anomaly instead of computing a fee.
Example fix
// before
let commission = compute_commission(fee_rate, exponent, size /* -5 */, price, side)?;
// after
anyhow::ensure!(size >= Decimal::ZERO, "invalid fill size {size}");
let commission = compute_commission(fee_rate, exponent, size, price, side)?; Defensive patterns
Strategy: validation
Validate before calling
let size = size.abs();
if size < Decimal::ZERO { return Err("negative fill size in report".into()); } Type guard
fn is_valid_fill_size(size: Decimal) -> bool { size >= Decimal::ZERO } Try / catch
let commission = match compute_commission(rate, exponent, size, price, side) {
Ok(c) => c,
Err(e) if e.to_string().contains("non-negative") => {
tracing::warn!("dropping malformed fill with negative size");
Decimal::ZERO
}
Err(e) => return Err(e),
}; Prevention
- Normalize fill quantities (abs / sign checks) when parsing venue fill reports.
- Validate fill reports against a schema before fee computation.
- Flag negative sizes as data-quality anomalies for upstream investigation.
When it happens
Trigger: Calling compute_commission (directly or via calculate_commission, parse_validated_fill_report, parse_validated_maker_fill_report) with size < 0 — e.g. a fill report carrying a signed negative quantity or a sign error when netting fills.
Common situations: Venue fill payloads parsed without abs()/sign normalization; maker/taker netting logic subtracting quantities into the negative; corrupted or hand-crafted fill report fixtures.
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
- PolymarketFeeModel requires a fill price in [0, 1]
- PolymarketFeeModel requires fee schedule exponent 1, was {}
- Polymarket fee rate must be greater than or equal to zero
- Polymarket rebate rate must be in [0, 1]
- builder fee rate must be non-negative
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c49cdc9ac5b54d19.
Report an issue: GitHub.